Skip to content

Commit

Permalink
feat: add mode publisher to manage component modes
Browse files Browse the repository at this point in the history
required to reduce file size of calcite.css
  • Loading branch information
alisonailea committed Oct 12, 2023
1 parent aa33ba3 commit 2772014
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@forward "~@esri/calcite-design-tokens/dist/scss/accordion-item";

%icon-position {
/* icon rotation variables */
--calcite-accordion-item-icon-rotation: calc(theme("rotate.90") * -1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { CSS_UTILITY } from "../../utils/resources";
import { SLOTS, CSS, IDS } from "./resources";
import { FlipContext, Position, Scale, SelectionMode } from "../interfaces";
import { RequestedItem } from "./interfaces";
import { getMode, Mode } from "../../utils/modePublisher";

/**
* @slot - A slot for adding custom content, including nested `calcite-accordion-item`s.
Expand Down Expand Up @@ -87,6 +88,8 @@ export class AccordionItem implements ConditionalSlotComponent {
*/
@Prop() scale: Scale;

@Prop({ mutable: true, reflect: true }) calciteMode: Mode;

//--------------------------------------------------------------------------
//
// Events
Expand All @@ -108,6 +111,11 @@ export class AccordionItem implements ConditionalSlotComponent {
// Lifecycle
//
//--------------------------------------------------------------------------
componentWillLoad(): void {
// TODO: check if this attribute is manually set by the user before getting the theme set in local storage.
// TODO: make this a part of the generic component setup.
this.calciteMode = getMode();
}

connectedCallback(): void {
connectConditionalSlotComponent(this);
Expand Down
53 changes: 53 additions & 0 deletions packages/calcite-components/src/utils/modePublisher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Default
let modeStore: Mode = "light";
// TODO: is this the right local storage key name?
export const storageKey = "calcite-theme";
export type Mode = "dark" | "light";
export type Disconnect = () => void;

export type ModePublisher<T> = () => {
(value: T): void;
subscribe(listener: (msg: T) => void): () => boolean;
};

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const modePublisher = <T>() => {
const listeners = new Set<(value: T) => void>();
function createPublisher(value: T) {
for (const cb of listeners) {
cb(value);
}
}
createPublisher.subscribe = (listener: (msg: T) => void) => {
listeners.add(listener);
return () => listeners.delete(listener);
};
return createPublisher;
};

type GetMode<T> = {
(): T;
subscribe(cb: (arg: T) => void): Disconnect;
};

if (window.matchMedia && window.matchMedia("(prefers-color-scheme: light)").matches) {
// is light
modeStore = "light";
} else if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
// is dark
modeStore = "dark";
}

let pub: ReturnType<ModePublisher<Mode>>;

export const getMode: GetMode<Mode> = () => (localStorage.getItem(storageKey) as Mode) ?? modeStore;

getMode.subscribe = (cb: (arg: Mode) => void) => {
pub = pub ?? modePublisher<Mode>();
return pub.subscribe(cb);
};

export const setMode = (mode: Mode): void => {
localStorage.setItem(storageKey, mode);
pub && pub(mode);
};

0 comments on commit 2772014

Please sign in to comment.