@weasel-js/forge 1.13.0-rc.0 → 1.14.0
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/README.md +1 -1
- package/dist/{FrameController-Tv3jrHyT.d.ts → FrameController-BM6xuEfY.d.ts} +18 -10
- package/dist/{chunk-KEQBGDUZ.js → chunk-B26DWEYT.js} +3 -3
- package/dist/{chunk-KEQBGDUZ.js.map → chunk-B26DWEYT.js.map} +1 -1
- package/dist/{chunk-3BAM6M26.js → chunk-FPF2JSWB.js} +3 -3
- package/dist/chunk-FPF2JSWB.js.map +1 -0
- package/dist/{chunk-ORMMZ5PV.js → chunk-MRYXJTDO.js} +7 -3
- package/dist/chunk-MRYXJTDO.js.map +1 -0
- package/dist/{chunk-35DOPXHZ.js → chunk-PGLOYXDP.js} +193 -190
- package/dist/chunk-PGLOYXDP.js.map +1 -0
- package/dist/{chunk-BUXUWAI4.js → chunk-PPB7VP6R.js} +62 -8
- package/dist/chunk-PPB7VP6R.js.map +1 -0
- package/dist/{chunk-STF6NQ5N.js → chunk-RVJHUY7W.js} +2 -2
- package/dist/chunk-RVJHUY7W.js.map +1 -0
- package/dist/{chunk-LTTEILXY.js → chunk-SFKDHXVE.js} +26 -4
- package/dist/chunk-SFKDHXVE.js.map +1 -0
- package/dist/chunk-STK2AZH2.js +11 -0
- package/dist/chunk-STK2AZH2.js.map +1 -0
- package/dist/chunk-TT4ZOYB6.js +143 -0
- package/dist/chunk-TT4ZOYB6.js.map +1 -0
- package/dist/{chunk-RKQ277P5.js → chunk-UDEUT7AG.js} +125 -80
- package/dist/chunk-UDEUT7AG.js.map +1 -0
- package/dist/{config-Bd6FVlh7.d.ts → config-DOjWyIui.d.ts} +3 -21
- package/dist/csf/preview-api.js +2 -2
- package/dist/frame/index.css +0 -2
- package/dist/frame/index.css.map +1 -1
- package/dist/frame/index.d.ts +14 -8
- package/dist/frame/index.js +114 -79
- package/dist/frame/index.js.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +4 -4
- package/dist/library-CdTj-hFp.d.ts +21 -0
- package/dist/{mountFrame-FdJDb3TB.d.ts → mountFrame-CRPAjg1M.d.ts} +1 -1
- package/dist/shell/index.css +166 -150
- package/dist/shell/index.css.map +1 -1
- package/dist/shell/index.d.ts +24 -5
- package/dist/shell/index.js +594 -402
- package/dist/shell/index.js.map +1 -1
- package/dist/test/index.css +2 -3
- package/dist/test/index.css.map +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.js +8 -10
- package/dist/test/index.js.map +1 -1
- package/dist/vite/index.js +127 -32
- package/dist/vite/index.js.map +1 -1
- package/package.json +11 -9
- package/dist/chunk-35DOPXHZ.js.map +0 -1
- package/dist/chunk-3BAM6M26.js.map +0 -1
- package/dist/chunk-BUXUWAI4.js.map +0 -1
- package/dist/chunk-GH5RE5X5.js +0 -10
- package/dist/chunk-GH5RE5X5.js.map +0 -1
- package/dist/chunk-L5XM5VKB.js +0 -47
- package/dist/chunk-L5XM5VKB.js.map +0 -1
- package/dist/chunk-LTTEILXY.js.map +0 -1
- package/dist/chunk-ORMMZ5PV.js.map +0 -1
- package/dist/chunk-RKQ277P5.js.map +0 -1
- package/dist/chunk-STF6NQ5N.js.map +0 -1
package/README.md
CHANGED
|
@@ -184,7 +184,7 @@ acts on the selected lens, or on the last one added when none is selected:
|
|
|
184
184
|
| `o` | compare with the opposite mode | `k` | choose a comparison |
|
|
185
185
|
| `Shift+O` | clear the comparison | `s` / `\` / `d` | Swap / Split / Difference |
|
|
186
186
|
| `t` | Token readout | `c` | Contrast readout |
|
|
187
|
-
| `g` | pixel grid | | |
|
|
187
|
+
| `g` | pixel grid | `b` | Glass: the reticle sits under the lens body |
|
|
188
188
|
|
|
189
189
|
Each binding's id is its action id (`loupe.add`, `loupe.view.split`, …), so a
|
|
190
190
|
binding override can rebind it. Alt+Slash opens a panel listing every key
|
|
@@ -74,6 +74,11 @@ interface A11yNode {
|
|
|
74
74
|
target: readonly string[];
|
|
75
75
|
html: string;
|
|
76
76
|
failureSummary?: string;
|
|
77
|
+
/** On a node axe could not decide: why, as axe's message key (`bgOverlap`, `pseudoContent`, …) and its own sentence. */
|
|
78
|
+
reason?: {
|
|
79
|
+
key?: string;
|
|
80
|
+
message?: string;
|
|
81
|
+
};
|
|
77
82
|
}
|
|
78
83
|
/** One axe rule's outcome on the story, with the elements it names. */
|
|
79
84
|
interface A11yFinding {
|
|
@@ -129,6 +134,12 @@ type ToFrame = {
|
|
|
129
134
|
| {
|
|
130
135
|
type: 'a11y.highlight';
|
|
131
136
|
targets: readonly (readonly string[])[];
|
|
137
|
+
}
|
|
138
|
+
/** Scrolls the frame document to `left`, `top` in CSS px: a lens's copy following its trial's frame. */
|
|
139
|
+
| {
|
|
140
|
+
type: 'scroll';
|
|
141
|
+
left: number;
|
|
142
|
+
top: number;
|
|
132
143
|
};
|
|
133
144
|
/** A message a story's frame sends the workshop. */
|
|
134
145
|
type FromFrame = {
|
|
@@ -162,6 +173,12 @@ type FromFrame = {
|
|
|
162
173
|
type: 'a11y';
|
|
163
174
|
id: string;
|
|
164
175
|
} & A11yOutcome)
|
|
176
|
+
/** Where the frame document stands, in CSS px: sent once after `ready`, then whenever it scrolls. */
|
|
177
|
+
| {
|
|
178
|
+
type: 'scroll';
|
|
179
|
+
left: number;
|
|
180
|
+
top: number;
|
|
181
|
+
}
|
|
165
182
|
/** `seq`, on a render fault only: how many `init`/`config`/`state`/`globals` messages the frame had received. */
|
|
166
183
|
| {
|
|
167
184
|
type: 'fault';
|
|
@@ -187,15 +204,6 @@ interface Span {
|
|
|
187
204
|
start: number;
|
|
188
205
|
end: number;
|
|
189
206
|
}
|
|
190
|
-
/** Everything a clock holds. */
|
|
191
|
-
interface ClockState {
|
|
192
|
-
/** The playhead, in ms, always inside `span`. */
|
|
193
|
-
time: number;
|
|
194
|
-
playing: boolean;
|
|
195
|
-
loop: boolean;
|
|
196
|
-
rate: number;
|
|
197
|
-
span: Span;
|
|
198
|
-
}
|
|
199
207
|
/** A span replacing the declared one at runtime, as `StoryTimeline.setSpan` takes it. */
|
|
200
208
|
type SpanOverride = Pick<TimelineSpec, 'duration' | 'start'>;
|
|
201
209
|
|
|
@@ -396,4 +404,4 @@ declare function startFrame({ story, channel, container, setup }: StartFrameOpti
|
|
|
396
404
|
/** Reports an import failure — there is no story to start. */
|
|
397
405
|
declare function reportImportFault(channel: Channel<ToFrame, FromFrame>, error: unknown): void;
|
|
398
406
|
|
|
399
|
-
export { type A11yFinding as A, type
|
|
407
|
+
export { type A11yFinding as A, type Channel as C, type DepGraph as D, type FrameSetup as F, type Globals as G, type IndexEntry as I, type Layout as L, type MetaSpec as M, type PlayContext as P, type StartFrameOptions as S, type ToFrame as T, type Viewport as V, type ConfigAnswers as a, type FaultPhase as b, type FromFrame as c, type StorySpec as d, type Span as e, type SpanOverride as f, type A11yNode as g, type A11yReport as h, type ComponentDeps as i, type ComponentHistory as j, type Decorator as k, type GlobalsTarget as l, type IndexContext as m, type IndexRender as n, type IndexStoryProps as o, type LoadedStory as p, type StoryContext as q, reportImportFault as r, startFrame as s, type TimelineSpec as t, type CssVarReport as u, type A11yOutcome as v, type DescribedEntry as w, type DescribedShape as x, type SchemaDescription as y, type SectionDescription as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stableStringify } from './chunk-
|
|
1
|
+
import { stableStringify } from './chunk-STK2AZH2.js';
|
|
2
2
|
import { createContext } from 'react';
|
|
3
3
|
import { isPlainObject } from '@weasel-js/core';
|
|
4
4
|
|
|
@@ -93,5 +93,5 @@ function withUnsent(sent, original) {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
export { ArgsContext, appliedLocal, coverOf, isPortSafe, portSafePart, withUnsent };
|
|
96
|
-
//# sourceMappingURL=chunk-
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
96
|
+
//# sourceMappingURL=chunk-B26DWEYT.js.map
|
|
97
|
+
//# sourceMappingURL=chunk-B26DWEYT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/csf/argsContext.ts","../src/csf/portSafe.ts"],"names":[],"mappings":"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","file":"chunk-KEQBGDUZ.js","sourcesContent":["import { type Context, createContext, type Dispatch, type SetStateAction } from 'react';\nimport { stableStringify } from '../protocol/messages';\n\ntype Args = Record<string, unknown>;\n\n/** A frame-local arg, and the config value it was set over: it applies only while config still holds that. */\nexport interface LocalArg {\n value: unknown;\n over: string;\n}\n\nexport type LocalArgs = Record<string, LocalArg>;\n\n/** A config value in the form `LocalArg.over` records. */\nexport const coverOf = (value: unknown): string => stableStringify(value) ?? ' undefined';\n\n/** The frame-local values that still apply over `config`. */\nexport const appliedLocal = (local: LocalArgs, config: Args): Args =>\n Object.fromEntries(\n Object.entries(local)\n .filter(([key, entry]) => coverOf(config[key]) === entry.over)\n .map(([key, entry]) => [key, entry.value]),\n );\n\nexport interface ArgsScope {\n /** The args the story renders with: its own, then config, then the frame-local ones that still apply. */\n args: Args;\n /** The trial's config as it stands. An `undefined` key means the story's own arg. */\n config: Args;\n defaults: Args;\n /** The story's own args, before config and the frame-local ones. */\n original: Args;\n setConfig: (path: string, value: unknown) => void;\n /** Args a MessagePort would not deliver intact, kept in the frame because config crosses one. */\n setLocal: Dispatch<SetStateAction<LocalArgs>>;\n}\n\nexport const ArgsContext: Context<ArgsScope | null> = createContext<ArgsScope | null>(null);\n","import { isPlainObject } from '@weasel-js/core';\n\nconst g = globalThis as Record<string, unknown>;\nconst CLONED_WHOLE = new Set<unknown>(\n [\n 'Date',\n 'RegExp',\n 'ArrayBuffer',\n 'DataView',\n 'Int8Array',\n 'Uint8Array',\n 'Uint8ClampedArray',\n 'Int16Array',\n 'Uint16Array',\n 'Int32Array',\n 'Uint32Array',\n 'Float16Array',\n 'Float32Array',\n 'Float64Array',\n 'BigInt64Array',\n 'BigUint64Array',\n ]\n .map((name) => (g[name] as { prototype?: object } | undefined)?.prototype)\n .filter(Boolean),\n);\n\n/** Own keys a clone keeps: enumerable string keys, plus an array's `length`. */\nconst hasOnlyClonedKeys = (v: object): boolean =>\n Reflect.ownKeys(v).every(\n (key) =>\n typeof key === 'string' &&\n (Object.prototype.propertyIsEnumerable.call(v, key) || (Array.isArray(v) && key === 'length')),\n );\n\n/**\n * Whether a MessagePort delivers `value` as the same thing it was. `structuredClone` succeeding is\n * not enough: it copies a class instance's fields onto a plain object and drops its methods.\n */\nexport function isPortSafe(value: unknown): boolean {\n const seen = new Set<object>();\n const safe = (v: unknown): boolean => {\n if (v === null) return true;\n if (typeof v !== 'object') return typeof v !== 'function' && typeof v !== 'symbol';\n if (seen.has(v)) return true;\n seen.add(v);\n const proto = Object.getPrototypeOf(v);\n if (CLONED_WHOLE.has(proto)) return true;\n if (proto === Map.prototype)\n return hasOnlyClonedKeys(v) && [...(v as Map<unknown, unknown>)].every(([key, member]) => safe(key) && safe(member));\n if (proto === Set.prototype) return hasOnlyClonedKeys(v) && [...(v as Set<unknown>)].every(safe);\n if (proto !== Array.prototype && proto !== Object.prototype && proto !== null) return false;\n return hasOnlyClonedKeys(v) && Object.values(v).every(safe);\n };\n try {\n return safe(value);\n } catch {\n return false;\n }\n}\n\n/** A plain object or array whose members can be split: React elements are plain objects, but whole. */\nconst splittable = (v: unknown): v is Record<string, unknown> | unknown[] =>\n (Array.isArray(v) ? Object.getPrototypeOf(v) === Array.prototype : isPlainObject(v) && !('$$typeof' in v)) &&\n hasOnlyClonedKeys(v as object);\n\n/**\n * The part of `value` a port delivers intact, or null when none of it can cross. A plain object\n * keeps its port-safe fields; an array holds null where a member has no part.\n */\nexport function portSafePart(value: unknown): { value: unknown } | null {\n const walking = new Set<object>();\n const part = (v: unknown): { value: unknown } | null => {\n if (isPortSafe(v)) return { value: v };\n if (!splittable(v) || walking.has(v)) return null;\n walking.add(v);\n try {\n if (Array.isArray(v)) return { value: v.map((member) => part(member)?.value ?? null) };\n const out: Record<string, unknown> = {};\n for (const [key, member] of Object.entries(v)) {\n const kept = part(member);\n if (kept) out[key] = kept.value;\n }\n return { value: out };\n } finally {\n walking.delete(v);\n }\n };\n try {\n return part(value);\n } catch {\n return null;\n }\n}\n\n/** `sent`, a value that crossed the port as `portSafePart(original)` or an edit of it, with what the part left behind put back. */\nexport function withUnsent(sent: unknown, original: unknown): unknown {\n if (isPortSafe(original)) return sent;\n if (sent === null && portSafePart(original) === null) return original;\n if (Array.isArray(original) && Array.isArray(sent))\n return sent.map((member, i) => (i < original.length ? withUnsent(member, original[i]) : member));\n if (!splittable(original) || Array.isArray(original) || !isPlainObject(sent)) return sent;\n const out: Record<string, unknown> = {};\n for (const [key, member] of Object.entries(original)) {\n if (key in sent) out[key] = withUnsent(sent[key], member);\n else if (portSafePart(member) === null) out[key] = member;\n }\n for (const [key, member] of Object.entries(sent)) if (!(key in original)) out[key] = member;\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/csf/argsContext.ts","../src/csf/portSafe.ts"],"names":[],"mappings":"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","file":"chunk-B26DWEYT.js","sourcesContent":["import { type Context, createContext, type Dispatch, type SetStateAction } from 'react';\nimport { stableStringify } from '../protocol/messages';\n\ntype Args = Record<string, unknown>;\n\n/** A frame-local arg, and the config value it was set over: it applies only while config still holds that. */\nexport interface LocalArg {\n value: unknown;\n over: string;\n}\n\nexport type LocalArgs = Record<string, LocalArg>;\n\n/** A config value in the form `LocalArg.over` records. */\nexport const coverOf = (value: unknown): string => stableStringify(value) ?? ' undefined';\n\n/** The frame-local values that still apply over `config`. */\nexport const appliedLocal = (local: LocalArgs, config: Args): Args =>\n Object.fromEntries(\n Object.entries(local)\n .filter(([key, entry]) => coverOf(config[key]) === entry.over)\n .map(([key, entry]) => [key, entry.value]),\n );\n\nexport interface ArgsScope {\n /** The args the story renders with: its own, then config, then the frame-local ones that still apply. */\n args: Args;\n /** The trial's config as it stands. An `undefined` key means the story's own arg. */\n config: Args;\n defaults: Args;\n /** The story's own args, before config and the frame-local ones. */\n original: Args;\n setConfig: (path: string, value: unknown) => void;\n /** Args a MessagePort would not deliver intact, kept in the frame because config crosses one. */\n setLocal: Dispatch<SetStateAction<LocalArgs>>;\n}\n\nexport const ArgsContext: Context<ArgsScope | null> = createContext<ArgsScope | null>(null);\n","import { isPlainObject } from '@weasel-js/core';\n\nconst g = globalThis as Record<string, unknown>;\nconst CLONED_WHOLE = new Set<unknown>(\n [\n 'Date',\n 'RegExp',\n 'ArrayBuffer',\n 'DataView',\n 'Int8Array',\n 'Uint8Array',\n 'Uint8ClampedArray',\n 'Int16Array',\n 'Uint16Array',\n 'Int32Array',\n 'Uint32Array',\n 'Float16Array',\n 'Float32Array',\n 'Float64Array',\n 'BigInt64Array',\n 'BigUint64Array',\n ]\n .map((name) => (g[name] as { prototype?: object } | undefined)?.prototype)\n .filter(Boolean),\n);\n\n/** Own keys a clone keeps: enumerable string keys, plus an array's `length`. */\nconst hasOnlyClonedKeys = (v: object): boolean =>\n Reflect.ownKeys(v).every(\n (key) =>\n typeof key === 'string' &&\n (Object.prototype.propertyIsEnumerable.call(v, key) || (Array.isArray(v) && key === 'length')),\n );\n\n/**\n * Whether a MessagePort delivers `value` as the same thing it was. `structuredClone` succeeding is\n * not enough: it copies a class instance's fields onto a plain object and drops its methods.\n */\nexport function isPortSafe(value: unknown): boolean {\n const seen = new Set<object>();\n const safe = (v: unknown): boolean => {\n if (v === null) return true;\n if (typeof v !== 'object') return typeof v !== 'function' && typeof v !== 'symbol';\n if (seen.has(v)) return true;\n seen.add(v);\n const proto = Object.getPrototypeOf(v);\n if (CLONED_WHOLE.has(proto)) return true;\n if (proto === Map.prototype)\n return hasOnlyClonedKeys(v) && [...(v as Map<unknown, unknown>)].every(([key, member]) => safe(key) && safe(member));\n if (proto === Set.prototype) return hasOnlyClonedKeys(v) && [...(v as Set<unknown>)].every(safe);\n if (proto !== Array.prototype && proto !== Object.prototype && proto !== null) return false;\n return hasOnlyClonedKeys(v) && Object.values(v).every(safe);\n };\n try {\n return safe(value);\n } catch {\n return false;\n }\n}\n\n/** A plain object or array whose members can be split: React elements are plain objects, but whole. */\nconst splittable = (v: unknown): v is Record<string, unknown> | unknown[] =>\n (Array.isArray(v) ? Object.getPrototypeOf(v) === Array.prototype : isPlainObject(v) && !('$$typeof' in v)) &&\n hasOnlyClonedKeys(v as object);\n\n/**\n * The part of `value` a port delivers intact, or null when none of it can cross. A plain object\n * keeps its port-safe fields; an array holds null where a member has no part.\n */\nexport function portSafePart(value: unknown): { value: unknown } | null {\n const walking = new Set<object>();\n const part = (v: unknown): { value: unknown } | null => {\n if (isPortSafe(v)) return { value: v };\n if (!splittable(v) || walking.has(v)) return null;\n walking.add(v);\n try {\n if (Array.isArray(v)) return { value: v.map((member) => part(member)?.value ?? null) };\n const out: Record<string, unknown> = {};\n for (const [key, member] of Object.entries(v)) {\n const kept = part(member);\n if (kept) out[key] = kept.value;\n }\n return { value: out };\n } finally {\n walking.delete(v);\n }\n };\n try {\n return part(value);\n } catch {\n return null;\n }\n}\n\n/** `sent`, a value that crossed the port as `portSafePart(original)` or an edit of it, with what the part left behind put back. */\nexport function withUnsent(sent: unknown, original: unknown): unknown {\n if (isPortSafe(original)) return sent;\n if (sent === null && portSafePart(original) === null) return original;\n if (Array.isArray(original) && Array.isArray(sent))\n return sent.map((member, i) => (i < original.length ? withUnsent(member, original[i]) : member));\n if (!splittable(original) || Array.isArray(original) || !isPlainObject(sent)) return sent;\n const out: Record<string, unknown> = {};\n for (const [key, member] of Object.entries(original)) {\n if (key in sent) out[key] = withUnsent(sent[key], member);\n else if (portSafePart(member) === null) out[key] = member;\n }\n for (const [key, member] of Object.entries(sent)) if (!(key in original)) out[key] = member;\n return out;\n}\n"]}
|
|
@@ -76,6 +76,6 @@ function withGlobals(schema, declarations) {
|
|
|
76
76
|
return f.schema({ ...schema.nodes, [GLOBALS_KEY]: group });
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
export { FOLLOW_APP, GLOBALS_KEY,
|
|
80
|
-
//# sourceMappingURL=chunk-
|
|
81
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
export { FOLLOW_APP, GLOBALS_KEY, effectiveGlobals, followApp, isForgePath, isGlobalsPath, labGlobals, labOptions, storyConfig, withGlobals };
|
|
80
|
+
//# sourceMappingURL=chunk-FPF2JSWB.js.map
|
|
81
|
+
//# sourceMappingURL=chunk-FPF2JSWB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shell/globals.ts"],"names":["from"],"mappings":"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","file":"chunk-FPF2JSWB.js","sourcesContent":["import { isPlainObject } from '@weasel-js/core';\nimport type { IconRef } from '@weasel-js/icons';\nimport type { LabMode } from '@weasel-js/labkit';\nimport { type ConfigSchema, f } from '@weasel-js/labkit/config';\nimport type { Globals } from '../protocol/messages';\n\n/** One global the workshop's toolbar sets for every story, and a trial may pin for its own. */\nexport interface GlobalDeclaration {\n label: string;\n options: readonly { value: string; label: string }[];\n default: string;\n /** Another global's key: the toolbar shows this one in a popover beside that one rather than in the bar itself. */\n under?: string;\n /** The glyph on the button opening the globals declared `under` this one. Default `core:tune`. */\n icon?: IconRef;\n /**\n * Whether the toolbar offers `value` given the lab's other values; every option shows when absent. `globals` is\n * resolved without any declaration's `shows`, so one `shows` cannot depend on another's outcome.\n */\n shows?: (value: string, globals: Globals) => boolean;\n /**\n * What this global reads from the lab's own chrome. Given, the lab's value may be `App` (`FOLLOW_APP`), offered\n * first, and while it is the global follows that chrome control, as the header's mode switch sets it. A trial's\n * pin follows the lab or names a value; it cannot follow the app on its own.\n */\n follows?: (chrome: LabChrome) => string;\n /**\n * The value opposite `value`, for the global a lens's opposite-mode comparison flips (`ShellConfig.loupe`'s\n * `modeGlobal`); undefined when it has none. `App` and `auto` are resolved to the mode they show before this is\n * asked. Absent, the lens swaps `light` and `dark`.\n */\n opposite?: (value: string, globals: Globals) => string | undefined;\n}\n\n/** The lab chrome's own settings a global can follow. */\nexport interface LabChrome {\n mode: LabMode;\n}\n\n/** The shell config's `globals`: each declaration by the key stories read it under. */\nexport type GlobalDeclarations = Readonly<Record<string, GlobalDeclaration>>;\n\n/** The config group every story schema gains, holding the trial's pins. A story never sees it. */\nexport const GLOBALS_KEY = '$globals';\n/** A pin's value when the trial follows the lab. */\nexport const FOLLOW_LAB = 'lab';\n/** A lab value, for a declaration that `follows` the app, meaning whatever the app's chrome is set to. */\nexport const FOLLOW_APP = 'app';\n\nconst APP_OPTION = { value: FOLLOW_APP, label: 'App' } as const;\n\nconst isRecord = isPlainObject;\n\nexport const isGlobalsPath = (path: string): boolean => path === GLOBALS_KEY || path.startsWith(`${GLOBALS_KEY}.`);\n\n/** The config key forge once kept a paused playhead under; a saved config may still hold it, so a story never sees it. */\nexport const PLAYHEAD_KEY = '$playhead';\n\n/** Config keys forge owns: a story neither sees nor writes them. */\nconst FORGE_KEYS: ReadonlySet<string> = new Set([GLOBALS_KEY, PLAYHEAD_KEY]);\n\n/** Whether a config path lies under a key forge owns. */\nexport const isForgePath = (path: string): boolean => FORGE_KEYS.has(path.split('.')[0]!);\n\n/** The options the toolbar offers for `declaration` at `globals`. */\nexport function shownOptions(declaration: GlobalDeclaration, globals: Globals): GlobalDeclaration['options'] {\n const { shows } = declaration;\n return shows ? declaration.options.filter((option) => shows(option.value, globals)) : declaration.options;\n}\n\n/** The options the lab's own control offers: `shownOptions`, after `App` where the declaration follows the app. */\nexport function labOptions(declaration: GlobalDeclaration, globals: Globals): GlobalDeclaration['options'] {\n const shown = shownOptions(declaration, globals);\n return declaration.follows ? [APP_OPTION, ...shown] : shown;\n}\n\n/** `values` with each `App` replaced by what its declaration reads from `chrome`; `values` itself when none is. */\nexport function followApp(declarations: GlobalDeclarations, values: Globals, chrome: LabChrome): Globals {\n const followed = Object.entries(declarations).flatMap(([key, { follows }]) =>\n follows && values[key] === FOLLOW_APP ? [[key, follows(chrome)] as const] : [],\n );\n return followed.length === 0 ? values : { ...values, ...Object.fromEntries(followed) };\n}\n\n/**\n * The lab's values from what was stored: declared keys only. A value no option offers falls back to the default, and\n * one its declaration's `shows` hides falls back to the shown option nearest it in `options`, the earlier on a tie.\n */\nexport function labGlobals(declarations: GlobalDeclarations, stored: unknown): Globals {\n const from = isRecord(stored) ? stored : {};\n const offered: Globals = Object.fromEntries(\n Object.entries(declarations).map(([key, declaration]) => {\n const value = from[key];\n const known =\n declaration.options.some((option) => option.value === value) || (declaration.follows && value === FOLLOW_APP);\n return [key, known ? value : declaration.default];\n }),\n );\n return Object.fromEntries(\n Object.entries(declarations).map(([key, declaration]) => {\n const shown = shownOptions(declaration, offered);\n const value = offered[key];\n if (value === FOLLOW_APP && declaration.follows) return [key, value];\n if (!declaration.shows || shown.length === 0 || shown.some((option) => option.value === value)) return [key, value];\n const at = (v: unknown) => declaration.options.findIndex((option) => option.value === v);\n const from = at(value);\n const nearest = shown.reduce((best, option) =>\n Math.abs(at(option.value) - from) < Math.abs(at(best.value) - from) ? option : best,\n );\n return [key, nearest.value];\n }),\n );\n}\n\n/** The lab's values, overridden by the pins in a trial's config that do not follow the lab. */\nexport function effectiveGlobals(lab: Globals, pins: unknown): Globals {\n if (!isRecord(pins)) return lab;\n const pinned = Object.entries(pins).filter(([key, value]) => key in lab && value !== FOLLOW_LAB);\n return pinned.length === 0 ? lab : { ...lab, ...Object.fromEntries(pinned) };\n}\n\n/**\n * The config a story receives: the trial's, without the keys forge owns. Returns `previous` when every other entry is\n * the same, so a change to a pin or the playhead alone is not a change to the story's config.\n */\nexport function storyConfig(config: unknown, previous?: unknown): unknown {\n if (!isRecord(config) || !Object.keys(config).some((key) => FORGE_KEYS.has(key))) return config;\n const rest = Object.fromEntries(Object.entries(config).filter(([key]) => !FORGE_KEYS.has(key)));\n if (isRecord(previous)) {\n const keys = Object.keys(rest);\n if (keys.length === Object.keys(previous).length && keys.every((key) => rest[key] === previous[key])) return previous;\n }\n return rest;\n}\n\n/** `schema` with a `$globals` group appended: one leaf per declaration, following the lab until pinned. */\nexport function withGlobals(schema: ConfigSchema<unknown>, declarations: GlobalDeclarations): ConfigSchema<unknown> {\n const entries = Object.entries(declarations);\n if (entries.length === 0) return schema;\n const leaves = Object.fromEntries(\n entries.map(([key, declaration]) => [\n key,\n f.enum(FOLLOW_LAB, [{ value: FOLLOW_LAB, label: 'Lab' }, ...declaration.options]).label(declaration.label),\n ]),\n );\n // An empty group name contributes rows without a heading of its own, under the section's.\n const group = f.group(leaves).label('').section('Globals', { layout: 'inline', pack: 'pairs', className: 'fg-globals-pins' });\n return f.schema({ ...schema.nodes, [GLOBALS_KEY]: group }) as ConfigSchema<unknown>;\n}\n"]}
|
|
@@ -3,6 +3,10 @@ import { isSafeOverride } from './chunk-5WS67HMU.js';
|
|
|
3
3
|
// src/title.ts
|
|
4
4
|
var DEFAULT_TITLE = "weaselforge";
|
|
5
5
|
|
|
6
|
+
// src/vite/issues/answer.ts
|
|
7
|
+
var ISSUES_PATH = "__forge/issues";
|
|
8
|
+
var issueLabel = (component) => `forge:${component}`;
|
|
9
|
+
|
|
6
10
|
// src/vite/capture/payload.ts
|
|
7
11
|
var messageOf = (err) => err instanceof Error ? err.message : String(err);
|
|
8
12
|
var CAPTURE_PATH = "__forge/capture";
|
|
@@ -54,6 +58,6 @@ function parsePayload(body) {
|
|
|
54
58
|
};
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
export { CAPTURE_PAGES, CAPTURE_PATH, DEFAULT_TITLE, MAX_DPR, MIN_DPR, messageOf, parsePayload };
|
|
58
|
-
//# sourceMappingURL=chunk-
|
|
59
|
-
//# sourceMappingURL=chunk-
|
|
61
|
+
export { CAPTURE_PAGES, CAPTURE_PATH, DEFAULT_TITLE, ISSUES_PATH, MAX_DPR, MIN_DPR, issueLabel, messageOf, parsePayload };
|
|
62
|
+
//# sourceMappingURL=chunk-MRYXJTDO.js.map
|
|
63
|
+
//# sourceMappingURL=chunk-MRYXJTDO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/title.ts","../src/vite/issues/answer.ts","../src/vite/capture/payload.ts"],"names":[],"mappings":"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","file":"chunk-MRYXJTDO.js","sourcesContent":["/** The workshop's name when the shell config gives none: in its header, and as the document title. */\nexport const DEFAULT_TITLE = 'weaselforge';\n","/** Where the issues endpoint answers, under the dev server's base. */\nexport const ISSUES_PATH = '__forge/issues';\n\n/** The label a component's issues carry. */\nexport const issueLabel = (component: string): string => `forge:${component}`;\n\n/** An open issue filed against a component. */\nexport interface ForgeIssue {\n number: number;\n title: string;\n url: string;\n /** When it was opened, as an ISO date. */\n opened: string;\n}\n\n/** The GitHub repository the dev server's checkout pushes to. */\nexport interface IssueRepo {\n /** `owner/name`. */\n slug: string;\n /** Its page, such as `https://github.com/owner/name`. */\n url: string;\n}\n\n/**\n * What a GET of the endpoint answers. `repo`, `branch` and `commit` describe the checkout whether or not `gh` can\n * list anything; exactly one of `issues`, `unavailable` and `error` is set.\n */\nexport interface IssuesAnswer {\n /** Null when `origin` names no GitHub repository. */\n repo: IssueRepo | null;\n /** Null on a detached head. */\n branch: string | null;\n commit: string | null;\n issues?: ForgeIssue[];\n /** Why nothing can be listed, when that is the machine's setup rather than a fault: no `gh`, no login, no repo. */\n unavailable?: string;\n /** What went wrong when `gh` was there and failed. */\n error?: string;\n}\n","import { isSafeOverride } from '../../frame/safeOverride.ts';\nimport type { Globals, Layout } from '../../protocol/messages.ts';\n\n/** Everything the screen renders a story from, as the capture endpoint takes it. */\nexport interface CapturePayload {\n /** The story's index id. */\n story: string;\n /** Picks the document: an isolated story renders under frame styles, any other under shell styles. */\n isolate: boolean;\n /** The story's config, with forge's `$` keys stripped and a comparison's args laid over. */\n config: unknown;\n /** Must survive JSON. */\n state: unknown;\n globals: Globals;\n /** CSS variable overrides, by property name. */\n overrides: Readonly<Record<string, string>>;\n /** Null for a story with no timeline, and for an isolated story. */\n playhead: number | null;\n /** The host's size in CSS pixels. */\n box: { width: number; height: number };\n layout: Layout;\n /** Device pixel ratio, in [1, 3]. */\n dpr: number;\n /** Where the story's scroller stands in its host, in CSS pixels, so the capture shows the patch the screen does. */\n scroll: { left: number; top: number };\n /** The workshop lab's theme as the screen shows it: the lab's globals, which the shell config's `labTheme` reads,\n * and its resolved color mode. An isolated story's document has no lab, and ignores it. */\n lab: { globals: Globals; mode: 'light' | 'dark' };\n /** The OS color scheme the screen sees, which the capture page emulates: a story or a lab in `auto` mode follows\n * `prefers-color-scheme`, and headless Chromium would otherwise answer light. */\n colorScheme: 'light' | 'dark';\n}\n\n/** What a capture failure says: an error's message, or anything else as a string. */\nexport const messageOf = (err: unknown): string => (err instanceof Error ? err.message : String(err));\n\n/** Where the endpoint answers, under the dev server's base. */\nexport const CAPTURE_PATH = '__forge/capture';\n\n/** The pages a capture renders on, under the dev server's base: one per document a story can render in. */\nexport const CAPTURE_PAGES = { shell: '__forge/capture.html', frame: '__forge/capture-frame.html' };\n\nexport const MIN_DPR = 1;\nexport const MAX_DPR = 3;\n\nconst LAYOUTS: readonly string[] = ['centered', 'padded', 'fullscreen'] satisfies readonly Layout[];\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst finite = (n: unknown): n is number => typeof n === 'number' && Number.isFinite(n);\nconst positive = (n: unknown): n is number => finite(n) && n > 0;\n\n/** Reads a request body as a payload, or names the first field it rejects. */\nexport function parsePayload(body: unknown): CapturePayload | { error: string } {\n if (!isRecord(body)) return { error: 'a capture payload is an object' };\n const { story, isolate, config, state, globals, overrides, playhead, box, layout, dpr, scroll, lab, colorScheme } = body;\n if (typeof story !== 'string' || story === '') return { error: 'story must be an index id' };\n if (typeof isolate !== 'boolean') return { error: 'isolate must be a boolean' };\n if (!isRecord(globals)) return { error: 'globals must be an object' };\n if (!isRecord(overrides) || !Object.values(overrides).every((v) => typeof v === 'string')) {\n return { error: 'overrides must map property names to strings' };\n }\n const unsafe = Object.entries(overrides as Record<string, string>).find(([name, value]) => !isSafeOverride(name, value));\n if (unsafe) return { error: `overrides must name custom properties, with no { } or ; in a value: ${unsafe[0]}` };\n if (playhead !== null && !(typeof playhead === 'number' && Number.isFinite(playhead))) {\n return { error: 'playhead must be a number or null' };\n }\n if (!isRecord(box) || !positive(box.width) || !positive(box.height)) {\n return { error: 'box must have a positive width and height' };\n }\n if (typeof layout !== 'string' || !LAYOUTS.includes(layout)) return { error: `layout must be one of ${LAYOUTS.join(', ')}` };\n if (typeof dpr !== 'number' || !(dpr >= MIN_DPR && dpr <= MAX_DPR)) return { error: `dpr must be in [${MIN_DPR}, ${MAX_DPR}]` };\n if (!isRecord(scroll) || !finite(scroll.left) || !finite(scroll.top)) return { error: 'scroll must hold a finite left and top' };\n if (!isRecord(lab) || !isRecord(lab.globals) || (lab.mode !== 'light' && lab.mode !== 'dark')) {\n return { error: 'lab must hold globals and a mode of light or dark' };\n }\n if (colorScheme !== 'light' && colorScheme !== 'dark') return { error: 'colorScheme must be light or dark' };\n return {\n story,\n isolate,\n config,\n state,\n globals,\n overrides: overrides as Record<string, string>,\n playhead,\n box: { width: box.width, height: box.height },\n layout: layout as Layout,\n dpr,\n scroll: { left: scroll.left, top: scroll.top },\n lab: { globals: lab.globals, mode: lab.mode },\n colorScheme,\n };\n}\n"]}
|