@unpunnyfuns/swatchbook-blocks 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +85 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -324,7 +324,7 @@ declare function useActiveAxes(): Readonly<Record<string, string>>;
|
|
|
324
324
|
* is safe to call from MDX doc blocks (where the preview-hooks context
|
|
325
325
|
* isn't available).
|
|
326
326
|
*/
|
|
327
|
-
declare const ColorFormatContext: _$react.Context<ColorFormat>;
|
|
327
|
+
declare const ColorFormatContext: _$react.Context<ColorFormat | null>;
|
|
328
328
|
declare function useColorFormat(): ColorFormat;
|
|
329
329
|
//#endregion
|
|
330
330
|
//#region src/provider.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Color from "colorjs.io";
|
|
2
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useState, useSyncExternalStore } from "react";
|
|
3
3
|
import { addons } from "storybook/preview-api";
|
|
4
4
|
import { axes, css, cssVarPrefix, defaultTheme, themes, themesResolved } from "virtual:swatchbook/tokens";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -178,6 +178,83 @@ function stringifyFallback(value, fallback) {
|
|
|
178
178
|
return fallback;
|
|
179
179
|
}
|
|
180
180
|
//#endregion
|
|
181
|
+
//#region src/internal/channel-globals.ts
|
|
182
|
+
const AXES_GLOBAL_KEY = "swatchbookAxes";
|
|
183
|
+
const THEME_GLOBAL_KEY = "swatchbookTheme";
|
|
184
|
+
const COLOR_FORMAT_GLOBAL_KEY = "swatchbookColorFormat";
|
|
185
|
+
let snapshot = {
|
|
186
|
+
axes: null,
|
|
187
|
+
theme: null,
|
|
188
|
+
format: null
|
|
189
|
+
};
|
|
190
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
191
|
+
let subscribed = false;
|
|
192
|
+
function isColorFormat(value) {
|
|
193
|
+
return typeof value === "string" && COLOR_FORMATS.includes(value);
|
|
194
|
+
}
|
|
195
|
+
function ensureSubscribed() {
|
|
196
|
+
if (subscribed || typeof window === "undefined") return;
|
|
197
|
+
subscribed = true;
|
|
198
|
+
const channel = addons.getChannel();
|
|
199
|
+
const onGlobals = (payload) => {
|
|
200
|
+
const globals = payload.globals;
|
|
201
|
+
if (!globals) return;
|
|
202
|
+
let next = snapshot;
|
|
203
|
+
const nextAxes = globals[AXES_GLOBAL_KEY];
|
|
204
|
+
if (nextAxes && typeof nextAxes === "object") next = {
|
|
205
|
+
...next,
|
|
206
|
+
axes: nextAxes
|
|
207
|
+
};
|
|
208
|
+
const nextTheme = globals[THEME_GLOBAL_KEY];
|
|
209
|
+
if (typeof nextTheme === "string") next = {
|
|
210
|
+
...next,
|
|
211
|
+
theme: nextTheme
|
|
212
|
+
};
|
|
213
|
+
const nextFormat = globals[COLOR_FORMAT_GLOBAL_KEY];
|
|
214
|
+
if (isColorFormat(nextFormat)) next = {
|
|
215
|
+
...next,
|
|
216
|
+
format: nextFormat
|
|
217
|
+
};
|
|
218
|
+
if (next !== snapshot) {
|
|
219
|
+
snapshot = next;
|
|
220
|
+
for (const cb of listeners) cb();
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* `setGlobals` fires once on preview init carrying the URL-persisted user
|
|
225
|
+
* globals (Storybook stores toolbar selections in `?globals=…`). Without
|
|
226
|
+
* this listener, deeplinking to an MDX page with a non-default axis tuple
|
|
227
|
+
* or color format renders defaults for one frame before the first
|
|
228
|
+
* `updateGlobals` arrives. `emitGlobals()` reads from `userGlobals.get()`
|
|
229
|
+
* (current state), so the payload is never stale — safe to handle.
|
|
230
|
+
*/
|
|
231
|
+
channel.on("globalsUpdated", onGlobals);
|
|
232
|
+
channel.on("updateGlobals", onGlobals);
|
|
233
|
+
channel.on("setGlobals", onGlobals);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Subscribe at module load so the `SET_GLOBALS` emission from preview init
|
|
237
|
+
* lands in our snapshot before any block renders. Running `useSyncExternalStore`'s
|
|
238
|
+
* `subscribe` lazily on first hook call would miss the event in most cases.
|
|
239
|
+
*/
|
|
240
|
+
ensureSubscribed();
|
|
241
|
+
function subscribe(cb) {
|
|
242
|
+
ensureSubscribed();
|
|
243
|
+
listeners.add(cb);
|
|
244
|
+
return () => {
|
|
245
|
+
listeners.delete(cb);
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function getSnapshot() {
|
|
249
|
+
return snapshot;
|
|
250
|
+
}
|
|
251
|
+
function getServerSnapshot() {
|
|
252
|
+
return snapshot;
|
|
253
|
+
}
|
|
254
|
+
function useChannelGlobals() {
|
|
255
|
+
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
181
258
|
//#region src/contexts.ts
|
|
182
259
|
/**
|
|
183
260
|
* Context carrying the full {@link ProjectSnapshot}. `null` sentinel lets
|
|
@@ -222,15 +299,15 @@ function useActiveAxes() {
|
|
|
222
299
|
* is safe to call from MDX doc blocks (where the preview-hooks context
|
|
223
300
|
* isn't available).
|
|
224
301
|
*/
|
|
225
|
-
const ColorFormatContext = createContext(
|
|
302
|
+
const ColorFormatContext = createContext(null);
|
|
226
303
|
function useColorFormat() {
|
|
227
|
-
|
|
304
|
+
const contextValue = useContext(ColorFormatContext);
|
|
305
|
+
const channelGlobals = useChannelGlobals();
|
|
306
|
+
return contextValue ?? channelGlobals.format ?? "hex";
|
|
228
307
|
}
|
|
229
308
|
//#endregion
|
|
230
309
|
//#region src/internal/use-project.ts
|
|
231
310
|
const STYLE_ELEMENT_ID = "swatchbook-tokens";
|
|
232
|
-
const GLOBAL_KEY = "swatchbookTheme";
|
|
233
|
-
const AXES_GLOBAL_KEY = "swatchbookAxes";
|
|
234
311
|
function ensureStylesheet(css) {
|
|
235
312
|
if (typeof document === "undefined") return;
|
|
236
313
|
let style = document.getElementById(STYLE_ELEMENT_ID);
|
|
@@ -288,32 +365,14 @@ function useProject() {
|
|
|
288
365
|
function useVirtualModuleFallback(enabled) {
|
|
289
366
|
const contextTheme = useActiveTheme();
|
|
290
367
|
const contextAxes = useActiveAxes();
|
|
291
|
-
const
|
|
292
|
-
const [channelAxes, setChannelAxes] = useState(null);
|
|
368
|
+
const channelGlobals = useChannelGlobals();
|
|
293
369
|
useEffect(() => {
|
|
294
370
|
if (!enabled) return;
|
|
295
371
|
ensureStylesheet(css);
|
|
296
372
|
}, [enabled]);
|
|
297
|
-
|
|
298
|
-
if (!enabled) return;
|
|
299
|
-
const channel = addons.getChannel();
|
|
300
|
-
const onGlobals = (payload) => {
|
|
301
|
-
const nextTheme = payload.globals?.[GLOBAL_KEY];
|
|
302
|
-
if (typeof nextTheme === "string") setChannelTheme(nextTheme);
|
|
303
|
-
const nextAxes = payload.globals?.[AXES_GLOBAL_KEY];
|
|
304
|
-
if (nextAxes && typeof nextAxes === "object") setChannelAxes(nextAxes);
|
|
305
|
-
};
|
|
306
|
-
channel.on("globalsUpdated", onGlobals);
|
|
307
|
-
channel.on("updateGlobals", onGlobals);
|
|
308
|
-
channel.on("setGlobals", onGlobals);
|
|
309
|
-
return () => {
|
|
310
|
-
channel.off("globalsUpdated", onGlobals);
|
|
311
|
-
channel.off("updateGlobals", onGlobals);
|
|
312
|
-
channel.off("setGlobals", onGlobals);
|
|
313
|
-
};
|
|
314
|
-
}, [enabled]);
|
|
315
|
-
const activeAxes = Object.keys(contextAxes).length > 0 ? { ...contextAxes } : channelAxes ?? defaultTuple(axes);
|
|
373
|
+
const activeAxes = Object.keys(contextAxes).length > 0 ? { ...contextAxes } : channelGlobals.axes ?? defaultTuple(axes);
|
|
316
374
|
const derivedName = nameForTuple(themes, activeAxes);
|
|
375
|
+
const channelTheme = channelGlobals.theme;
|
|
317
376
|
const fallbackTupleName = channelTheme && tupleForName(themes, channelTheme) ? channelTheme : null;
|
|
318
377
|
const activeTheme = contextTheme || derivedName || fallbackTupleName || channelTheme || defaultTheme || themes[0]?.name || "";
|
|
319
378
|
return {
|