forgebook 0.2.0 → 0.3.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 +112 -5
- package/dist/bin/forgebook/agentLoopCommands.mjs +3 -0
- package/dist/bin/forgebook/agentText.d.ts +2 -2
- package/dist/bin/forgebook/agentText.js +15 -13
- package/dist/bin/forgebook/agents.md +21 -6
- package/dist/bin/forgebook/mcpTools.js +1 -1
- package/dist/bin/forgebook/newStoriesFile.js +7 -2
- package/dist/bin/forgebook-docs/collectDocs.js +1 -1
- package/dist/src/argsProps.d.ts +32 -0
- package/dist/src/argsProps.js +69 -0
- package/dist/src/catalogue.d.ts +48 -5
- package/dist/src/catalogue.js +47 -8
- package/dist/src/frame/mountFrame.js +26 -7
- package/dist/src/frame/touchCaret.d.ts +43 -0
- package/dist/src/frame/touchCaret.js +195 -0
- package/dist/src/frame/touchEvents.d.ts +3 -2
- package/dist/src/frame/touchEvents.js +17 -18
- package/dist/src/frame/touchLayer.js +48 -7
- package/dist/src/propGroups.d.ts +66 -3
- package/dist/src/propGroups.js +67 -13
- package/dist/src/shell/ApiReference.d.ts +9 -4
- package/dist/src/shell/ApiReference.js +47 -39
- package/dist/src/shell/AudienceSections.js +1 -1
- package/dist/src/shell/ComponentPage.d.ts +5 -2
- package/dist/src/shell/ComponentPage.js +4 -18
- package/dist/src/shell/DocBlocks.js +1 -1
- package/dist/src/shell/PropRows.d.ts +42 -0
- package/dist/src/shell/PropRows.js +60 -0
- package/dist/src/shell/PropsTab.d.ts +14 -10
- package/dist/src/shell/PropsTab.js +18 -58
- package/dist/src/shell/RequiredFirstSwitch.d.ts +16 -0
- package/dist/src/shell/RequiredFirstSwitch.js +8 -0
- package/dist/src/shell/Stage.js +11 -23
- package/dist/src/shell/StoryCoverage.js +4 -1
- package/dist/src/shell/docPage.css +6 -0
- package/dist/src/shell/dockTabs.d.ts +7 -5
- package/dist/src/shell/dockTabs.js +4 -4
- package/dist/src/shell/reportedPanel.d.ts +12 -0
- package/dist/src/shell/reportedPanel.js +19 -0
- package/dist/src/shell/shell.css +56 -1
- package/dist/src/shell/strings.d.ts +2 -0
- package/dist/src/shell/strings.js +2 -0
- package/dist/src/shell/usePanelDocs.d.ts +11 -0
- package/dist/src/shell/usePanelDocs.js +29 -0
- package/dist/src/shell/useRequiredFirst.d.ts +27 -0
- package/dist/src/shell/useRequiredFirst.js +67 -0
- package/dist/src/storyCheck.d.ts +2 -0
- package/dist/src/storyCheck.js +2 -1
- package/dist/src/storyGlobals.js +2 -1
- package/dist/src/storyTree.d.ts +11 -1
- package/dist/src/storyTree.js +3 -1
- package/dist/src/viewState.d.ts +7 -0
- package/dist/src/viewState.js +13 -0
- package/dist/src/vite/agent.types.d.ts +12 -0
- package/dist/src/vite/agentApi.js +6 -1
- package/dist/src/vite/agentRoutes.js +18 -4
- package/dist/src/vite/builtTexts.d.ts +2 -2
- package/dist/src/vite/builtTexts.js +7 -6
- package/dist/src/vite/configFile.d.ts +3 -2
- package/dist/src/vite/configFile.js +63 -14
- package/dist/src/vite/docPagesModule.d.ts +10 -7
- package/dist/src/vite/docPagesModule.js +14 -11
- package/dist/src/vite/docsExtractor.d.ts +6 -0
- package/dist/src/vite/docsExtractor.js +13 -0
- package/dist/src/vite/fileAccess.d.ts +51 -0
- package/dist/src/vite/fileAccess.js +109 -0
- package/dist/src/vite/forgebookPlugin.d.ts +1 -1
- package/dist/src/vite/forgebookPlugin.js +61 -96
- package/dist/src/vite/framesServer.js +21 -5
- package/dist/src/vite/generatedModules.d.ts +23 -0
- package/dist/src/vite/generatedModules.js +58 -0
- package/dist/src/vite/hotSnippets.js +7 -3
- package/dist/src/vite/indexStoryFile.d.ts +2 -2
- package/dist/src/vite/indexStoryFile.js +2 -2
- package/dist/src/vite/indexedParameters.d.ts +1 -1
- package/dist/src/vite/indexedParameters.js +21 -1
- package/dist/src/vite/originGuard.d.ts +14 -4
- package/dist/src/vite/originGuard.js +15 -6
- package/dist/src/vite/pages.d.ts +3 -2
- package/dist/src/vite/pages.js +23 -16
- package/dist/src/vite/pluginIds.d.ts +9 -2
- package/dist/src/vite/pluginIds.js +21 -6
- package/dist/src/vite/pluginModules.d.ts +39 -10
- package/dist/src/vite/pluginModules.js +67 -22
- package/dist/src/vite/prebundled.js +2 -1
- package/dist/src/vite/searchModule.d.ts +6 -4
- package/dist/src/vite/searchModule.js +8 -7
- package/dist/src/vite/storyFilesModule.d.ts +59 -27
- package/dist/src/vite/storyFilesModule.js +88 -58
- package/dist/src/vite/storyPatterns.d.ts +39 -0
- package/dist/src/vite/storyPatterns.js +100 -0
- package/dist/src/vite/textQueries.d.ts +7 -1
- package/dist/src/vite/textQueries.js +7 -1
- package/package.json +2 -2
|
@@ -1,69 +1,27 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { isNamedArg } from "../messages.js";
|
|
5
|
-
import { groupedProps, propGroupOrder } from "../propGroups.js";
|
|
2
|
+
import { isNamedProp, settableProps } from "../argTypes.js";
|
|
3
|
+
import { canOrderRequired, laidOutProps, propGroupOrder } from "../propGroups.js";
|
|
6
4
|
import { useCatalogue } from "./catalogueContext.js";
|
|
7
5
|
import { Icon } from "./icons.js";
|
|
8
|
-
import {
|
|
6
|
+
import { PropControl, ReadOnlyProp, Toggle } from "./PropRows.js";
|
|
7
|
+
import { RequiredFirstSwitch } from "./RequiredFirstSwitch.js";
|
|
9
8
|
import { STRINGS } from "./strings.js";
|
|
10
|
-
|
|
11
|
-
const pickerColor = (value) => typeof value === "string" && /^#[0-9a-f]{6}$/i.test(value) ? value : "#000000";
|
|
9
|
+
import { useRequiredFirst } from "./useRequiredFirst.js";
|
|
12
10
|
/** No prop named by a text key. */
|
|
13
11
|
const NO_TEXT_ARGS = {};
|
|
14
12
|
/** No group named first. */
|
|
15
13
|
const NO_GROUPS = [];
|
|
16
|
-
/** A prop's name, whether it is required, and its type (whole in the tooltip when it is cut). */
|
|
17
|
-
const PropHead = ({ prop }) => (_jsxs("div", { className: "forgebook-prop__head", children: [_jsxs("code", { className: "forgebook-prop__name", children: [prop.label ?? prop.name, prop.isRequired ? (_jsx("span", { className: "forgebook-prop__required", title: STRINGS.required, children: "*" })) : null] }), _jsx("code", { className: "forgebook-prop__type", title: prop.type, children: prop.type })] }));
|
|
18
|
-
/** A prop's description and default, under its control. */
|
|
19
|
-
const PropNote = ({ id, prop }) => prop.description === "" && prop.defaultValue === undefined ? null : (_jsxs("p", { id: id, className: "forgebook-prop__description", children: [prop.description, prop.defaultValue === undefined ? null : (_jsxs(_Fragment, { children: [prop.description === "" ? null : " ", STRINGS.defaultIs, " ", _jsx("code", { children: prop.defaultValue })] }))] }));
|
|
20
|
-
/**
|
|
21
|
-
* Where a prop's text comes from, under its field: the key of the story's text, and a way back to it once the panel
|
|
22
|
-
* wrote over it.
|
|
23
|
-
*
|
|
24
|
-
* @param props - the note, the prop's name and the value setter.
|
|
25
|
-
*/
|
|
26
|
-
const TextArgLine = ({ note, name, onValueChange }) => (_jsxs("p", { className: "forgebook-prop__text-arg", children: [STRINGS.fromTexts, " ", _jsx("code", { children: note.key }), note.isChanged ? (_jsx("button", { type: "button", className: "forgebook-text-button", onClick: () => onValueChange(name, undefined), children: STRINGS.backToText })) : null] }));
|
|
27
|
-
/** One adjustable prop with its control. */
|
|
28
|
-
const PropControl = ({ prop, value, named, textArg, onValueChange }) => {
|
|
29
|
-
// the description is shown under the control and named by it, so the control's name is the prop alone
|
|
30
|
-
const descriptionId = useId();
|
|
31
|
-
const label = prop.label ?? prop.name;
|
|
32
|
-
if (named !== undefined) {
|
|
33
|
-
return (_jsxs("div", { className: "forgebook-prop", children: [_jsx(PropHead, { prop: prop }), _jsxs("select", { "aria-label": label, "aria-describedby": descriptionId, value: isNamedArg(value) ? value.named : "", onChange: (event) => {
|
|
34
|
-
const chosen = event.target.value;
|
|
35
|
-
onValueChange(prop.name, chosen === "" ? undefined : { of: prop.type, named: chosen });
|
|
36
|
-
}, children: [_jsx("option", { value: "", children: STRINGS.unset }), Object.keys(named).map((name) => (_jsx("option", { value: name, children: name }, name)))] }), _jsx(PropNote, { id: descriptionId, prop: prop })] }));
|
|
37
|
-
}
|
|
38
|
-
if (prop.kind === "choice") {
|
|
39
|
-
return (_jsxs("div", { className: "forgebook-prop", children: [_jsx(PropHead, { prop: prop }), _jsx(ChoiceControl, { prop: prop, value: value, descriptionId: descriptionId, onValueChange: onValueChange }), _jsx(PropNote, { id: descriptionId, prop: prop })] }));
|
|
40
|
-
}
|
|
41
|
-
if (prop.kind === "number") {
|
|
42
|
-
return (_jsxs("div", { className: "forgebook-prop", children: [_jsx(PropHead, { prop: prop }), _jsx("div", { className: "forgebook-prop__field", children: _jsx(NumberField, { prop: prop, value: value, descriptionId: descriptionId, onValueChange: onValueChange }) }), _jsx(PropNote, { id: descriptionId, prop: prop })] }));
|
|
43
|
-
}
|
|
44
|
-
return (_jsxs("div", { className: "forgebook-prop", children: [_jsx(PropHead, { prop: prop }), _jsxs("div", { className: "forgebook-prop__field", children: [_jsx("input", { type: "text", "aria-label": label, "aria-describedby": descriptionId, value: textOf(value), onChange: (event) => {
|
|
45
|
-
const text = event.target.value;
|
|
46
|
-
onValueChange(prop.name, text === "" ? undefined : text);
|
|
47
|
-
} }), isColorProp(prop) ? (_jsx("input", { type: "color", className: "forgebook-prop__color", "aria-label": STRINGS.pickColor(label), value: pickerColor(value), onChange: (event) => onValueChange(prop.name, event.target.value) })) : null] }), textArg === undefined ? null : (_jsx(TextArgLine, { note: textArg, name: prop.name, onValueChange: onValueChange })), _jsx(PropNote, { id: descriptionId, prop: prop })] }));
|
|
48
|
-
};
|
|
49
|
-
/** A toggle: its name in a compact checkbox, its description as the tooltip and for screen readers. */
|
|
50
|
-
const Toggle = ({ prop, value, onValueChange }) => {
|
|
51
|
-
const descriptionId = useId();
|
|
52
|
-
return (_jsxs("label", { className: "forgebook-toggle", title: prop.description, children: [_jsx("input", { type: "checkbox", checked: value === true, "aria-describedby": descriptionId, onChange: (event) => onValueChange(prop.name, event.target.checked) }), _jsx("code", { children: prop.label ?? prop.name }), _jsx("span", { id: descriptionId, className: "forgebook-visually-hidden", children: prop.description })] }));
|
|
53
|
-
};
|
|
54
|
-
/** A prop the panel cannot set: its name, its type and its description, for reading. */
|
|
55
|
-
const ReadOnlyProp = ({ prop }) => (_jsxs("div", { className: "forgebook-prop", children: [_jsx(PropHead, { prop: prop }), _jsx("p", { className: "forgebook-prop__description", children: prop.description })] }));
|
|
56
14
|
/**
|
|
57
15
|
* A group the props' TSDoc names, under its name: its controls in the order of the props, its toggles, then the props
|
|
58
|
-
* the panel cannot set.
|
|
16
|
+
* the panel cannot set. The "Required" group is drawn as one, each of its props naming its own group.
|
|
59
17
|
*
|
|
60
|
-
* @param props - the group's name and props,
|
|
18
|
+
* @param props - the group's name and props, how each prop is drawn, and whether it is the "Required" group.
|
|
61
19
|
*/
|
|
62
|
-
const NamedGroup = ({ name, props, isSettable, control, toggle }) => {
|
|
20
|
+
const NamedGroup = ({ name, props, isSettable, control, toggle, isRequired = false }) => {
|
|
63
21
|
const controls = props.filter((prop) => isSettable(prop) && prop.kind !== "toggle");
|
|
64
22
|
const toggles = props.filter((prop) => isSettable(prop) && prop.kind === "toggle");
|
|
65
23
|
const others = props.filter((prop) => !isSettable(prop));
|
|
66
|
-
return (_jsx("div", { className: "forgebook-prop-group", children: _jsxs("details", { className: "forgebook-fold", open: true, children: [_jsxs("summary", { className: "forgebook-fold__summary forgebook-prop-group__title", children: [_jsx(Icon, { name: "chevronRight", size: 12 }), _jsx("h3", { className: "forgebook-fold__name", children: name }), _jsx("span", { className: "forgebook-fold__count", children: STRINGS.propCount(props.length) })] }), _jsxs("div", { className: "forgebook-prop-group__body", children: [controls.length === 0 ? null : _jsx("div", { className: "forgebook-prop-grid", children: controls.map(control) }), toggles.length === 0 ? null : _jsx("div", { className: "forgebook-toggles", children: toggles.map(toggle) }), others.length === 0 ? null : (_jsx("div", { className: "forgebook-prop-grid", children: others.map((prop) => (_jsx(ReadOnlyProp, { prop: prop }, prop.name))) }))] })] }) }));
|
|
24
|
+
return (_jsx("div", { className: "forgebook-prop-group", "data-required": isRequired || undefined, children: _jsxs("details", { className: "forgebook-fold", open: true, children: [_jsxs("summary", { className: "forgebook-fold__summary forgebook-prop-group__title", children: [_jsx(Icon, { name: "chevronRight", size: 12 }), _jsx("h3", { className: "forgebook-fold__name", children: name }), _jsx("span", { className: "forgebook-fold__count", children: STRINGS.propCount(props.length) })] }), _jsxs("div", { className: "forgebook-prop-group__body", children: [controls.length === 0 ? null : (_jsx("div", { className: "forgebook-prop-grid", children: controls.map((prop) => control(prop, isRequired)) })), toggles.length === 0 ? null : (_jsx("div", { className: "forgebook-toggles", children: toggles.map((prop) => toggle(prop, isRequired)) })), others.length === 0 ? null : (_jsx("div", { className: "forgebook-prop-grid", children: others.map((prop) => (_jsx(ReadOnlyProp, { prop: prop, showsGroup: isRequired }, prop.name))) }))] })] }) }));
|
|
67
25
|
};
|
|
68
26
|
/**
|
|
69
27
|
* The worst case's button, and once it is on, how many elements spill (the frame outlines them).
|
|
@@ -76,17 +34,19 @@ const WorstCaseControl = ({ worstCase }) => (_jsxs(_Fragment, { children: [_jsx(
|
|
|
76
34
|
*
|
|
77
35
|
* @param props - the props, the values, which props the story lets the panel set, and the setters.
|
|
78
36
|
*/
|
|
79
|
-
export const PropsTab = ({ props, values, controls, onValueChange, onReset, worstCase, namedValues = {}, textArgs = NO_TEXT_ARGS, componentGroups = NO_GROUPS }) => {
|
|
37
|
+
export const PropsTab = ({ props, values, controls, onValueChange, onReset, worstCase, namedValues = {}, textArgs = NO_TEXT_ARGS, componentGroups = NO_GROUPS, requiredFirst }) => {
|
|
80
38
|
const catalogue = useCatalogue();
|
|
39
|
+
const ordering = useRequiredFirst(requiredFirst);
|
|
81
40
|
const isNamed = (prop) => isNamedProp(prop, namedValues);
|
|
82
41
|
const allSettable = settableProps(props, controls, namedValues);
|
|
83
42
|
const isSettable = (prop) => allSettable.includes(prop);
|
|
84
|
-
const
|
|
85
|
-
|
|
43
|
+
const listed = props.filter((prop) => prop.kind !== "event");
|
|
44
|
+
const { required, groups: propGroups } = laidOutProps(listed, propGroupOrder(componentGroups, catalogue.propGroups), ordering.layout);
|
|
45
|
+
// the props that name no group are drawn as the tab always drew them, by control, in the layout's order
|
|
86
46
|
const ungrouped = propGroups.find((group) => group.name === undefined)?.props ?? [];
|
|
87
|
-
const settable =
|
|
88
|
-
const control = (prop) => (_jsx(PropControl, { prop: prop, value: values[prop.name], named: isNamed(prop) ? namedValues[prop.type] : undefined, textArg: textArgs[prop.name], onValueChange: onValueChange }, prop.name));
|
|
89
|
-
const toggle = (prop) => (_jsx(Toggle, { prop: prop, value: values[prop.name], onValueChange: onValueChange }, prop.name));
|
|
47
|
+
const settable = ungrouped.filter(isSettable);
|
|
48
|
+
const control = (prop, showsGroup) => (_jsx(PropControl, { prop: prop, showsGroup: showsGroup, value: values[prop.name], named: isNamed(prop) ? namedValues[prop.type] : undefined, textArg: textArgs[prop.name], onValueChange: onValueChange }, prop.name));
|
|
49
|
+
const toggle = (prop, showsGroup) => (_jsx(Toggle, { prop: prop, showsGroup: showsGroup, value: values[prop.name], onValueChange: onValueChange }, prop.name));
|
|
90
50
|
const groups = [
|
|
91
51
|
{
|
|
92
52
|
title: STRINGS.propGroups.choice,
|
|
@@ -100,5 +60,5 @@ export const PropsTab = ({ props, values, controls, onValueChange, onReset, wors
|
|
|
100
60
|
const toggles = settable.filter((prop) => prop.kind === "toggle");
|
|
101
61
|
const others = ungrouped.filter((prop) => !isSettable(prop));
|
|
102
62
|
const hasControls = controls === "all" || controls.length > 0;
|
|
103
|
-
return (_jsxs("div", { className: "forgebook-tab-props", children: [hasControls ? null : _jsx("p", { className: "forgebook-tab-note", children: STRINGS.fixedExamples }), groups.map((group) => (_jsxs("div", { className: "forgebook-prop-group", children: [_jsx("h3", { className: "forgebook-prop-group__title", children: group.title }), _jsx("div", { className: "forgebook-prop-grid", children: group.props.map(control) })] }, group.title))), toggles.length === 0 ? null : (_jsxs("div", { className: "forgebook-prop-group", children: [_jsx("h3", { className: "forgebook-prop-group__title", children: STRINGS.propGroups.toggle }), _jsx("div", { className: "forgebook-toggles", children: toggles.map(toggle) })] })), others.length === 0 ? null : (_jsxs("div", { className: "forgebook-prop-group", children: [_jsx("h3", { className: "forgebook-prop-group__title", children: hasControls ? STRINGS.otherProps : STRINGS.allProps }), _jsx("div", { className: "forgebook-prop-grid", children: others.map((prop) => (_jsx(ReadOnlyProp, { prop: prop }, prop.name))) })] })), propGroups.map((group) => group.name === undefined ? null : (_jsx(NamedGroup, { name: group.name, props: group.props, isSettable: isSettable, control: control, toggle: toggle }, group.name))), hasControls ? (_jsxs("div", { className: "forgebook-tab-foot", children: [_jsx("button", { type: "button", className: "forgebook-text-button", onClick: onReset, children: STRINGS.resetArgs }), worstCase?.canApply === true ? _jsx(WorstCaseControl, { worstCase: worstCase }) : null] })) : null] }));
|
|
63
|
+
return (_jsxs("div", { className: "forgebook-tab-props", children: [canOrderRequired(listed) ? (_jsx("div", { className: "forgebook-tab-head", children: _jsx(RequiredFirstSwitch, { state: ordering }) })) : null, hasControls ? null : _jsx("p", { className: "forgebook-tab-note", children: STRINGS.fixedExamples }), required.length === 0 ? null : (_jsx(NamedGroup, { name: STRINGS.required, props: required, isSettable: isSettable, control: control, toggle: toggle, isRequired: true })), groups.map((group) => (_jsxs("div", { className: "forgebook-prop-group", children: [_jsx("h3", { className: "forgebook-prop-group__title", children: group.title }), _jsx("div", { className: "forgebook-prop-grid", children: group.props.map((prop) => control(prop, false)) })] }, group.title))), toggles.length === 0 ? null : (_jsxs("div", { className: "forgebook-prop-group", children: [_jsx("h3", { className: "forgebook-prop-group__title", children: STRINGS.propGroups.toggle }), _jsx("div", { className: "forgebook-toggles", children: toggles.map((prop) => toggle(prop, false)) })] })), others.length === 0 ? null : (_jsxs("div", { className: "forgebook-prop-group", children: [_jsx("h3", { className: "forgebook-prop-group__title", children: hasControls ? STRINGS.otherProps : STRINGS.allProps }), _jsx("div", { className: "forgebook-prop-grid", children: others.map((prop) => (_jsx(ReadOnlyProp, { prop: prop, showsGroup: false }, prop.name))) })] })), propGroups.map((group) => group.name === undefined ? null : (_jsx(NamedGroup, { name: group.name, props: group.props, isSettable: isSettable, control: control, toggle: toggle }, group.name))), hasControls ? (_jsxs("div", { className: "forgebook-tab-foot", children: [_jsx("button", { type: "button", className: "forgebook-text-button", onClick: onReset, children: STRINGS.resetArgs }), worstCase?.canApply === true ? _jsx(WorstCaseControl, { worstCase: worstCase }) : null] })) : null] }));
|
|
104
64
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "Required first" switch in the header of a props table (the API reference, the Props tab): the reader turns the
|
|
3
|
+
* ordering of the required props on or off for every component (`useRequiredFirst.ts`).
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { ReactNode } from "react";
|
|
8
|
+
import type { RequiredFirstState } from "./useRequiredFirst.ts";
|
|
9
|
+
/**
|
|
10
|
+
* The switch.
|
|
11
|
+
*
|
|
12
|
+
* @param props - its state, from `useRequiredFirst`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const RequiredFirstSwitch: ({ state }: {
|
|
15
|
+
readonly state: Pick<RequiredFirstState, "isOn" | "setIsOn">;
|
|
16
|
+
}) => ReactNode;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { STRINGS } from "./strings.js";
|
|
3
|
+
/**
|
|
4
|
+
* The switch.
|
|
5
|
+
*
|
|
6
|
+
* @param props - its state, from `useRequiredFirst`.
|
|
7
|
+
*/
|
|
8
|
+
export const RequiredFirstSwitch = ({ state }) => (_jsxs("label", { className: "forgebook-required-first", title: STRINGS.requiredFirstHint, children: [_jsx("input", { type: "checkbox", role: "switch", "aria-checked": state.isOn, className: "forgebook-switch", checked: state.isOn, onChange: (event) => state.setIsOn(event.currentTarget.checked) }), STRINGS.requiredFirst] }));
|
package/dist/src/shell/Stage.js
CHANGED
|
@@ -15,7 +15,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
|
|
|
15
15
|
import { panelProps, settableProps } from "../argTypes.js";
|
|
16
16
|
import { matrixOf, matrixProps } from "../matrix.js";
|
|
17
17
|
import { panelArgsParam, parsePanelArgsParam } from "../messages.js";
|
|
18
|
-
import {
|
|
18
|
+
import { withFixed, withOwnFixed } from "../storyGlobals.js";
|
|
19
19
|
import { frameAddress, isComparing, liveView, schemeOf, viewParams } from "../viewState.js";
|
|
20
20
|
import { useStoryClockControls } from "./ClockControls.js";
|
|
21
21
|
import { useCatalogue } from "./catalogueContext.js";
|
|
@@ -25,22 +25,21 @@ import { DroppedArgsNote } from "./DroppedArgsNote.js";
|
|
|
25
25
|
import { dockTabs } from "./dockTabs.js";
|
|
26
26
|
import { FrameView, tellFrames } from "./FrameView.js";
|
|
27
27
|
import { framesOrigin } from "./framesOrigin.js";
|
|
28
|
+
import { reportedPanel } from "./reportedPanel.js";
|
|
28
29
|
import { StageCompare } from "./StageCompare.js";
|
|
29
30
|
import { StageTools } from "./StageTools.js";
|
|
30
31
|
import { StageViewport } from "./StageViewport.js";
|
|
31
32
|
import { StoryBar } from "./StoryBar.js";
|
|
32
33
|
import { STRINGS } from "./strings.js";
|
|
33
34
|
import { useAddressArgs } from "./useAddressArgs.js";
|
|
34
|
-
import { useComponentDocs } from "./useComponentDocs.js";
|
|
35
35
|
import { useFrameMessages } from "./useFrameMessages.js";
|
|
36
36
|
import { useLiveView, useLoadedView } from "./useLiveView.js";
|
|
37
|
+
import { usePanelDocs } from "./usePanelDocs.js";
|
|
37
38
|
import { usePluginStory, usePluginTabs } from "./usePluginTabs.js";
|
|
38
39
|
import { useScrollMemory } from "./useScrollMemory.js";
|
|
39
40
|
import { useStoryCheck } from "./useStoryCheck.js";
|
|
40
41
|
import { useStoryCode } from "./useStoryCode.js";
|
|
41
42
|
import { useWorstCase } from "./useWorstCase.js";
|
|
42
|
-
/** The `argTypes` of a story before its frame reported them. */
|
|
43
|
-
const NO_ARG_TYPES = {};
|
|
44
43
|
/**
|
|
45
44
|
* What the stage's handles set the width with; none, so no handles, when the story fixes the width.
|
|
46
45
|
*
|
|
@@ -49,20 +48,6 @@ const NO_ARG_TYPES = {};
|
|
|
49
48
|
* @param onViewChange - the view's setter.
|
|
50
49
|
*/
|
|
51
50
|
const widthSetter = (fixed, view, onViewChange) => fixed.width === undefined ? (width) => onViewChange({ ...view, width }) : undefined;
|
|
52
|
-
/**
|
|
53
|
-
* A story's `argTypes`, controls, actions and fixed view for the panel and the stage: as its frame read them once it ran, which sees a setting
|
|
54
|
-
* written by code the index leaves out; the index's controls and no `argTypes` or actions before.
|
|
55
|
-
*
|
|
56
|
-
* @param panels - what each story's frame reported, by story.
|
|
57
|
-
* @param story - the story.
|
|
58
|
-
*/
|
|
59
|
-
const reportedPanel = (panels, story) => panels.get(story.id) ?? {
|
|
60
|
-
argTypes: NO_ARG_TYPES,
|
|
61
|
-
controls: story.controls,
|
|
62
|
-
actions: [],
|
|
63
|
-
fixed: NOT_FIXED,
|
|
64
|
-
parameters: []
|
|
65
|
-
};
|
|
66
51
|
/** The height of the first frame before its story reports its own, in CSS px. */
|
|
67
52
|
const INITIAL_FRAME_HEIGHT = 240;
|
|
68
53
|
/** The most calls the Events tab keeps. */
|
|
@@ -105,7 +90,6 @@ const embedHeight = (view, contentHeight, story) => view.height === "auto" ? Mat
|
|
|
105
90
|
export const Stage = ({ component, story, view: ownView, onViewChange: onOwnViewChange, onFixedChange, panelArgs, onPanelArgsChange, matrixAxes, onMatrixAxesChange, frameUrl, plugins, loadCode, loadDocs, namedValues, header, onShownWidthChange, measuredHeight, backgroundOf, scroll }) => {
|
|
106
91
|
const frameRef = useRef(null);
|
|
107
92
|
const storyRef = useRef(null);
|
|
108
|
-
const docs = useComponentDocs(loadDocs);
|
|
109
93
|
const code = useStoryCode(loadCode);
|
|
110
94
|
// the story's own args, as each frame reported them, by story
|
|
111
95
|
const [storyArgs, setStoryArgs] = useState(new Map());
|
|
@@ -115,14 +99,17 @@ export const Stage = ({ component, story, view: ownView, onViewChange: onOwnView
|
|
|
115
99
|
const [storyPanels, setStoryPanels] = useState(new Map());
|
|
116
100
|
// the story is drawn with what it fixes of the view; a change from here keeps the user's own in the address
|
|
117
101
|
const panel = reportedPanel(storyPanels, story);
|
|
118
|
-
const
|
|
102
|
+
const catalogue = useCatalogue();
|
|
103
|
+
const docs = usePanelDocs(loadDocs, component.name, storyArgs.get(story.id), panel.actions);
|
|
104
|
+
// kept while neither changes: every new switches' object sends the frames the view, and a story whose height moves
|
|
105
|
+
// renders the stage at each report
|
|
106
|
+
const view = useMemo(() => withFixed(ownView, panel.fixed), [ownView, panel.fixed]);
|
|
119
107
|
const onViewChange = (changed) => onOwnViewChange(withOwnFixed(changed, ownView, panel.fixed));
|
|
120
108
|
const [calls, setCalls] = useState([]);
|
|
121
109
|
// each story's play trace, by story: a trace belongs to the story that played
|
|
122
110
|
const [traces, setTraces] = useState(new Map());
|
|
123
111
|
// what each plugin's frame module last told its tab, by story: a plugin's report belongs to the story that sent it
|
|
124
112
|
const [pluginReports, setPluginReports] = useState(new Map());
|
|
125
|
-
const catalogue = useCatalogue();
|
|
126
113
|
const { switches } = catalogue;
|
|
127
114
|
const storyCheck = useStoryCheck(frameRef, frameAddress(frameUrl, story.id, view, switches));
|
|
128
115
|
const eventNames = useMemo(() => docs.status === "ready"
|
|
@@ -192,6 +179,8 @@ export const Stage = ({ component, story, view: ownView, onViewChange: onOwnView
|
|
|
192
179
|
onSpills: worstCase.receive,
|
|
193
180
|
onPluginReport: (message) => setPluginReports((current) => new Map(current).set(`${message.storyId}|${message.plugin}`, message)),
|
|
194
181
|
// a story that changes its own args changes the panel's values, as the reader would
|
|
182
|
+
// a story that could not be shown reports no args: the panel built from them has none, rather than waiting
|
|
183
|
+
onFailed: (storyId) => setStoryArgs((current) => (current.has(storyId) ? current : new Map(current).set(storyId, {}))),
|
|
195
184
|
onStoryArgs: (storyId, args) => storyId === story.id ? onPanelArgsChange(args) : undefined
|
|
196
185
|
});
|
|
197
186
|
// the docs may arrive after the frames: they learn the events then
|
|
@@ -254,8 +243,7 @@ export const Stage = ({ component, story, view: ownView, onViewChange: onOwnView
|
|
|
254
243
|
const tabs = dockTabs({
|
|
255
244
|
docs,
|
|
256
245
|
code,
|
|
257
|
-
|
|
258
|
-
isLogic: story.isLogic,
|
|
246
|
+
story,
|
|
259
247
|
componentName: component.name,
|
|
260
248
|
argTypes: panel.argTypes,
|
|
261
249
|
controls: panel.controls,
|
|
@@ -16,6 +16,7 @@ import { groupLabel } from "../catalogue.js";
|
|
|
16
16
|
import { groupedStories } from "../storyTree.js";
|
|
17
17
|
import { AUDIENCE_TEXTS } from "./audiencePage.js";
|
|
18
18
|
import { CodeText } from "./CodeText.js";
|
|
19
|
+
import { useCatalogue } from "./catalogueContext.js";
|
|
19
20
|
import { StoryLink } from "./Example.js";
|
|
20
21
|
import { framesOrigin } from "./framesOrigin.js";
|
|
21
22
|
import { a11yHint } from "./tabSummaries.js";
|
|
@@ -118,9 +119,11 @@ const checkText = (check) => {
|
|
|
118
119
|
*/
|
|
119
120
|
export const StoryCoverage = ({ stories, storyGroups, queue, pageRef, settled, hrefOf, onOpen }) => {
|
|
120
121
|
const { checks, checkAll } = usePageChecks(pageRef, queue, settled);
|
|
122
|
+
// a catalogue that checks no accessibility has no column for it, nor a check to run
|
|
123
|
+
const hasA11y = useCatalogue().a11y !== undefined;
|
|
121
124
|
const ordered = groupedStories(stories, storyGroups.map((group) => group.id)).flatMap((section) => section.stories);
|
|
122
125
|
const played = stories.filter((story) => story.hasPlay).length;
|
|
123
126
|
const untested = stories.filter(isUntested).length;
|
|
124
127
|
const finished = [...checks.values()].filter((check) => check.status !== "running").length;
|
|
125
|
-
return (_jsxs("section", { className: "forgebook-doc__section", "aria-labelledby": "forgebook-coverage", children: [_jsx("h2", { id: "forgebook-coverage", children: AUDIENCE_TEXTS.coverage }), _jsxs("div", { className: "forgebook-coverage__head", children: [_jsx("p", { className: "forgebook-coverage__summary", children: AUDIENCE_TEXTS.coverageSummary(stories.length, played, untested) }), _jsx("button", { type: "button", className: "forgebook-button", onClick: checkAll, children: AUDIENCE_TEXTS.coverageCheckAll })] }), _jsx("p", { className: "forgebook-coverage__progress", role: "status", children: checks.size === 0 ? "" : AUDIENCE_TEXTS.coverageChecked(finished, stories.length) }), _jsx("div", { className: "forgebook-api", children: _jsxs("table", { className: "forgebook-api__table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageStory }), _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageGroup }), _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coveragePlay }), _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageTests }), _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageA11y })] }) }), _jsx("tbody", { children: ordered.map((story) => (_jsxs("tr", { children: [_jsxs("th", { scope: "row", className: "forgebook-coverage__story", children: [_jsx(StoryLink, { story: story, hrefOf: hrefOf, onOpen: onOpen, className: "forgebook-link", children: story.name }), story.description === undefined ? null : (_jsx("span", { className: "forgebook-coverage__covers", children: _jsx(CodeText, { text: story.description }) }))] }), _jsx("td", { children: story.group === undefined ? "" : groupLabel(storyGroups, story.group) }), _jsx("td", { children: story.hasPlay ? AUDIENCE_TEXTS.coverageHasPlay : AUDIENCE_TEXTS.coverageNoPlay }), _jsx("td", { children: isUntested(story) ? AUDIENCE_TEXTS.coverageUntested : AUDIENCE_TEXTS.coverageTested }), _jsx("td", { children: checkText(checks.get(story.id)) })] }, story.id))) })] }) })] }));
|
|
128
|
+
return (_jsxs("section", { className: "forgebook-doc__section", "aria-labelledby": "forgebook-coverage", children: [_jsx("h2", { id: "forgebook-coverage", children: AUDIENCE_TEXTS.coverage }), _jsxs("div", { className: "forgebook-coverage__head", children: [_jsx("p", { className: "forgebook-coverage__summary", children: AUDIENCE_TEXTS.coverageSummary(stories.length, played, untested) }), hasA11y ? (_jsx("button", { type: "button", className: "forgebook-button", onClick: checkAll, children: AUDIENCE_TEXTS.coverageCheckAll })) : null] }), hasA11y ? (_jsx("p", { className: "forgebook-coverage__progress", role: "status", children: checks.size === 0 ? "" : AUDIENCE_TEXTS.coverageChecked(finished, stories.length) })) : null, _jsx("div", { className: "forgebook-api", children: _jsxs("table", { className: "forgebook-api__table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageStory }), _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageGroup }), _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coveragePlay }), _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageTests }), hasA11y ? _jsx("th", { scope: "col", children: AUDIENCE_TEXTS.coverageA11y }) : null] }) }), _jsx("tbody", { children: ordered.map((story) => (_jsxs("tr", { children: [_jsxs("th", { scope: "row", className: "forgebook-coverage__story", children: [_jsx(StoryLink, { story: story, hrefOf: hrefOf, onOpen: onOpen, className: "forgebook-link", children: story.name }), story.description === undefined ? null : (_jsx("span", { className: "forgebook-coverage__covers", children: _jsx(CodeText, { text: story.description }) }))] }), _jsx("td", { children: story.group === undefined ? "" : groupLabel(storyGroups, story.group) }), _jsx("td", { children: story.hasPlay ? AUDIENCE_TEXTS.coverageHasPlay : AUDIENCE_TEXTS.coverageNoPlay }), _jsx("td", { children: isUntested(story) ? AUDIENCE_TEXTS.coverageUntested : AUDIENCE_TEXTS.coverageTested }), hasA11y ? _jsx("td", { children: checkText(checks.get(story.id)) }) : null] }, story.id))) })] }) })] }));
|
|
126
129
|
};
|
|
@@ -168,6 +168,7 @@
|
|
|
168
168
|
.forgebook-aside {
|
|
169
169
|
--forgebook-tone: var(--forgebook-accent-text);
|
|
170
170
|
display: grid;
|
|
171
|
+
grid-template-columns: minmax(0, 1fr);
|
|
171
172
|
gap: 0.5rem;
|
|
172
173
|
min-width: 0;
|
|
173
174
|
margin: 0;
|
|
@@ -199,6 +200,7 @@
|
|
|
199
200
|
}
|
|
200
201
|
.forgebook-tabs {
|
|
201
202
|
display: grid;
|
|
203
|
+
grid-template-columns: minmax(0, 1fr);
|
|
202
204
|
gap: 0.75rem;
|
|
203
205
|
min-width: 0;
|
|
204
206
|
}
|
|
@@ -234,6 +236,7 @@
|
|
|
234
236
|
}
|
|
235
237
|
.forgebook-tabs__panel {
|
|
236
238
|
display: grid;
|
|
239
|
+
grid-template-columns: minmax(0, 1fr);
|
|
237
240
|
gap: 1rem;
|
|
238
241
|
min-width: 0;
|
|
239
242
|
}
|
|
@@ -242,6 +245,7 @@
|
|
|
242
245
|
}
|
|
243
246
|
.forgebook-steps {
|
|
244
247
|
display: grid;
|
|
248
|
+
grid-template-columns: minmax(0, 1fr);
|
|
245
249
|
gap: 1.25rem;
|
|
246
250
|
margin: 0;
|
|
247
251
|
padding: 0;
|
|
@@ -251,6 +255,7 @@
|
|
|
251
255
|
.forgebook-steps__step {
|
|
252
256
|
position: relative;
|
|
253
257
|
display: grid;
|
|
258
|
+
grid-template-columns: minmax(0, 1fr);
|
|
254
259
|
gap: 0.75rem;
|
|
255
260
|
min-width: 0;
|
|
256
261
|
padding-inline-start: calc(1.75rem + 0.75rem);
|
|
@@ -288,6 +293,7 @@
|
|
|
288
293
|
}
|
|
289
294
|
.forgebook-card {
|
|
290
295
|
display: grid;
|
|
296
|
+
grid-template-columns: minmax(0, 1fr);
|
|
291
297
|
align-content: start;
|
|
292
298
|
gap: 0.5rem;
|
|
293
299
|
min-width: 0;
|
|
@@ -16,9 +16,10 @@ import { type ComponentDocs } from "../componentDocs.ts";
|
|
|
16
16
|
import type { ArgValue, PanelArgs } from "../messages.ts";
|
|
17
17
|
import type { NamedValues } from "../namedValues.ts";
|
|
18
18
|
import type { PlayTrace } from "../playTrace.ts";
|
|
19
|
+
import type { TreeStory } from "../storyTree.ts";
|
|
19
20
|
import type { CheckState } from "./A11yTab.tsx";
|
|
20
21
|
import type { DockTab } from "./Dock.tsx";
|
|
21
|
-
import {
|
|
22
|
+
import type { TextArgNote } from "./PropRows.tsx";
|
|
22
23
|
import type { EventCall } from "./useFrameMessages.ts";
|
|
23
24
|
import type { Loaded } from "./useLoaded.ts";
|
|
24
25
|
import type { WorstCaseState } from "./worstArgs.ts";
|
|
@@ -28,10 +29,11 @@ export type DockTabsInput = {
|
|
|
28
29
|
readonly docs: Loaded<ComponentDocs>;
|
|
29
30
|
/** The story file's code, as loaded. */
|
|
30
31
|
readonly code: Loaded<StoryFileCode>;
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
/**
|
|
33
|
+
* The story: its export name, whether it is about logic (its hook's signature comes first), and where it puts the
|
|
34
|
+
* required props (none for the catalogue's).
|
|
35
|
+
*/
|
|
36
|
+
readonly story: Pick<TreeStory, "exportName" | "isLogic" | "requiredFirst">;
|
|
35
37
|
/** The component's name from the sidebar, for the JSX when the docs have none. */
|
|
36
38
|
readonly componentName: string;
|
|
37
39
|
/** The props the story lets the panel set. */
|
|
@@ -30,7 +30,7 @@ const propsTab = (input, props) => props.some((prop) => prop.kind !== "event")
|
|
|
30
30
|
{
|
|
31
31
|
id: "props",
|
|
32
32
|
label: STRINGS.tabs.props,
|
|
33
|
-
content: (_jsx(PropsTab, { props: props, values: input.values, controls: input.controls, onValueChange: input.onValueChange, onReset: input.onReset, worstCase: input.worstCase, namedValues: input.namedValues, textArgs: input.textArgs, componentGroups: input.propGroups }))
|
|
33
|
+
content: (_jsx(PropsTab, { props: props, values: input.values, controls: input.controls, onValueChange: input.onValueChange, onReset: input.onReset, worstCase: input.worstCase, namedValues: input.namedValues, textArgs: input.textArgs, componentGroups: input.propGroups, requiredFirst: input.story.requiredFirst }))
|
|
34
34
|
}
|
|
35
35
|
]
|
|
36
36
|
: [];
|
|
@@ -78,7 +78,7 @@ const docsTabs = (input) => {
|
|
|
78
78
|
];
|
|
79
79
|
}
|
|
80
80
|
// the docs' place while they load or fail: the tab the story opens on once they are read
|
|
81
|
-
const docsTab = input.isLogic
|
|
81
|
+
const docsTab = input.story.isLogic
|
|
82
82
|
? { id: "signature", label: STRINGS.tabs.signature }
|
|
83
83
|
: { id: "props", label: STRINGS.tabs.props };
|
|
84
84
|
// the play's trace comes from the frame, not from the docs: a first read of a project's docs can take seconds, and a
|
|
@@ -91,7 +91,7 @@ const docsTabs = (input) => {
|
|
|
91
91
|
}
|
|
92
92
|
const component = docs.value;
|
|
93
93
|
const events = eventsOf(component.props, input.actions);
|
|
94
|
-
if (input.isLogic)
|
|
94
|
+
if (input.story.isLogic)
|
|
95
95
|
return logicTabs(input, component);
|
|
96
96
|
const tabs = [];
|
|
97
97
|
tabs.push(...propsTab(input, panelProps(component.props, input.argTypes)));
|
|
@@ -158,7 +158,7 @@ const codeTabs = (input) => {
|
|
|
158
158
|
label: STRINGS.tabs.code,
|
|
159
159
|
content: (_jsx(LazyTab, { module: CODE_TAB, tabProps: {
|
|
160
160
|
code: code.value,
|
|
161
|
-
exportName: input.exportName,
|
|
161
|
+
exportName: input.story.exportName,
|
|
162
162
|
componentName: docs.status === "ready" ? codeNameOf(docs.value) : input.componentName,
|
|
163
163
|
args: input.values
|
|
164
164
|
} }))
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TreeStory } from "../storyTree.ts";
|
|
2
|
+
import type { ReadyMessage } from "./useFrameMessages.ts";
|
|
3
|
+
/** What a story's frame reports for the panel and the stage. */
|
|
4
|
+
export type ReportedPanel = Pick<ReadyMessage, "argTypes" | "controls" | "actions" | "fixed" | "parameters">;
|
|
5
|
+
/**
|
|
6
|
+
* A story's `argTypes`, controls, actions and fixed view for the panel and the stage: as its frame read them once it ran, which sees a setting
|
|
7
|
+
* written by code the index leaves out; the index's controls and no `argTypes` or actions before.
|
|
8
|
+
*
|
|
9
|
+
* @param panels - what each story's frame reported, by story.
|
|
10
|
+
* @param story - the story.
|
|
11
|
+
*/
|
|
12
|
+
export declare const reportedPanel: (panels: ReadonlyMap<string, ReportedPanel>, story: TreeStory) => ReportedPanel;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NOT_FIXED } from "../storyGlobals.js";
|
|
2
|
+
/** The `argTypes` of a story before its frame reported them. */
|
|
3
|
+
const NO_ARG_TYPES = {};
|
|
4
|
+
/** No actions, as one value: the panel's docs made from the args are kept while it stays the same. */
|
|
5
|
+
const NO_ACTIONS = [];
|
|
6
|
+
/**
|
|
7
|
+
* A story's `argTypes`, controls, actions and fixed view for the panel and the stage: as its frame read them once it ran, which sees a setting
|
|
8
|
+
* written by code the index leaves out; the index's controls and no `argTypes` or actions before.
|
|
9
|
+
*
|
|
10
|
+
* @param panels - what each story's frame reported, by story.
|
|
11
|
+
* @param story - the story.
|
|
12
|
+
*/
|
|
13
|
+
export const reportedPanel = (panels, story) => panels.get(story.id) ?? {
|
|
14
|
+
argTypes: NO_ARG_TYPES,
|
|
15
|
+
controls: story.controls,
|
|
16
|
+
actions: NO_ACTIONS,
|
|
17
|
+
fixed: NOT_FIXED,
|
|
18
|
+
parameters: []
|
|
19
|
+
};
|
package/dist/src/shell/shell.css
CHANGED
|
@@ -453,6 +453,7 @@
|
|
|
453
453
|
}
|
|
454
454
|
.forgebook-story {
|
|
455
455
|
display: grid;
|
|
456
|
+
grid-template-columns: minmax(0, 1fr);
|
|
456
457
|
gap: 0.625rem;
|
|
457
458
|
margin: 1rem 2rem 2rem;
|
|
458
459
|
min-width: 0;
|
|
@@ -464,6 +465,7 @@
|
|
|
464
465
|
}
|
|
465
466
|
.forgebook-story__bar {
|
|
466
467
|
display: flex;
|
|
468
|
+
flex-wrap: wrap;
|
|
467
469
|
align-items: center;
|
|
468
470
|
gap: 0.5rem;
|
|
469
471
|
}
|
|
@@ -598,6 +600,11 @@
|
|
|
598
600
|
grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
|
|
599
601
|
gap: 0.75rem 1.25rem;
|
|
600
602
|
}
|
|
603
|
+
.forgebook-tab-head {
|
|
604
|
+
display: flex;
|
|
605
|
+
justify-content: flex-end;
|
|
606
|
+
padding: 0.625rem 0.875rem 0;
|
|
607
|
+
}
|
|
601
608
|
.forgebook-tab-note {
|
|
602
609
|
margin: 0;
|
|
603
610
|
padding: 0.75rem 0.875rem 0;
|
|
@@ -1549,8 +1556,9 @@
|
|
|
1549
1556
|
font: 400 0.6875rem/1.6 var(--forgebook-font-mono);
|
|
1550
1557
|
}
|
|
1551
1558
|
.forgebook-stage__heading {
|
|
1552
|
-
flex: 1;
|
|
1559
|
+
flex: 1 1 10rem;
|
|
1553
1560
|
display: grid;
|
|
1561
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1554
1562
|
gap: 0.125rem;
|
|
1555
1563
|
min-width: 0;
|
|
1556
1564
|
}
|
|
@@ -1559,6 +1567,7 @@
|
|
|
1559
1567
|
font: 500 0.8125rem/1.35 var(--forgebook-font-sans);
|
|
1560
1568
|
font-weight: 600;
|
|
1561
1569
|
color: var(--forgebook-text);
|
|
1570
|
+
overflow-wrap: break-word;
|
|
1562
1571
|
}
|
|
1563
1572
|
.forgebook-stage__description {
|
|
1564
1573
|
display: -webkit-box;
|
|
@@ -1622,6 +1631,7 @@
|
|
|
1622
1631
|
}
|
|
1623
1632
|
.forgebook-viewport {
|
|
1624
1633
|
display: grid;
|
|
1634
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1625
1635
|
gap: 0.375rem;
|
|
1626
1636
|
}
|
|
1627
1637
|
.forgebook-viewport__canvas {
|
|
@@ -1726,15 +1736,18 @@
|
|
|
1726
1736
|
.forgebook-home {
|
|
1727
1737
|
box-sizing: border-box;
|
|
1728
1738
|
display: grid;
|
|
1739
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1729
1740
|
gap: 1.5rem;
|
|
1730
1741
|
width: 100%;
|
|
1731
1742
|
max-width: 56rem;
|
|
1732
1743
|
margin: 0 auto;
|
|
1733
1744
|
padding: 1.5rem 2rem 2rem;
|
|
1745
|
+
overflow-wrap: break-word;
|
|
1734
1746
|
animation: forgebook-rise 260ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
|
|
1735
1747
|
}
|
|
1736
1748
|
.forgebook-home__head {
|
|
1737
1749
|
display: grid;
|
|
1750
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1738
1751
|
gap: 0.5rem;
|
|
1739
1752
|
}
|
|
1740
1753
|
.forgebook-home__title {
|
|
@@ -1766,6 +1779,7 @@
|
|
|
1766
1779
|
}
|
|
1767
1780
|
.forgebook-home__recent-link {
|
|
1768
1781
|
display: grid;
|
|
1782
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1769
1783
|
gap: 0.125rem;
|
|
1770
1784
|
padding: 0.5rem 0.75rem;
|
|
1771
1785
|
border-radius: var(--forgebook-radius-control);
|
|
@@ -1805,6 +1819,7 @@
|
|
|
1805
1819
|
}
|
|
1806
1820
|
.forgebook-home__card {
|
|
1807
1821
|
display: grid;
|
|
1822
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1808
1823
|
align-content: start;
|
|
1809
1824
|
justify-items: start;
|
|
1810
1825
|
gap: 0.5rem;
|
|
@@ -1821,6 +1836,7 @@
|
|
|
1821
1836
|
width: 100%;
|
|
1822
1837
|
margin: 0;
|
|
1823
1838
|
font: 600 0.875rem/1.3 var(--forgebook-font-sans);
|
|
1839
|
+
overflow-wrap: anywhere;
|
|
1824
1840
|
}
|
|
1825
1841
|
.forgebook-home__count {
|
|
1826
1842
|
font: 400 0.6875rem/1.35 var(--forgebook-font-sans);
|
|
@@ -1829,6 +1845,7 @@
|
|
|
1829
1845
|
}
|
|
1830
1846
|
.forgebook-home__components {
|
|
1831
1847
|
display: grid;
|
|
1848
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1832
1849
|
gap: 0.25rem;
|
|
1833
1850
|
margin: 0;
|
|
1834
1851
|
padding: 0;
|
|
@@ -1903,6 +1920,7 @@
|
|
|
1903
1920
|
}
|
|
1904
1921
|
.forgebook-doc__section {
|
|
1905
1922
|
display: grid;
|
|
1923
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1906
1924
|
gap: 1rem;
|
|
1907
1925
|
}
|
|
1908
1926
|
.forgebook-doc__section > h2 {
|
|
@@ -1916,6 +1934,7 @@
|
|
|
1916
1934
|
}
|
|
1917
1935
|
.forgebook-doc__group {
|
|
1918
1936
|
display: grid;
|
|
1937
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1919
1938
|
gap: 1.5rem;
|
|
1920
1939
|
}
|
|
1921
1940
|
.forgebook-doc__group-name {
|
|
@@ -1938,10 +1957,12 @@
|
|
|
1938
1957
|
}
|
|
1939
1958
|
.forgebook-example {
|
|
1940
1959
|
display: grid;
|
|
1960
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1941
1961
|
gap: 0.625rem;
|
|
1942
1962
|
}
|
|
1943
1963
|
.forgebook-example__head {
|
|
1944
1964
|
display: grid;
|
|
1965
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1945
1966
|
gap: 0.25rem;
|
|
1946
1967
|
}
|
|
1947
1968
|
.forgebook-example__title {
|
|
@@ -2152,6 +2173,7 @@
|
|
|
2152
2173
|
.forgebook-prose {
|
|
2153
2174
|
font: 400 0.8125rem/1.4 var(--forgebook-font-sans);
|
|
2154
2175
|
line-height: 1.6;
|
|
2176
|
+
overflow-wrap: break-word;
|
|
2155
2177
|
}
|
|
2156
2178
|
.forgebook-prose > :first-child {
|
|
2157
2179
|
margin-top: 0;
|
|
@@ -2218,6 +2240,7 @@
|
|
|
2218
2240
|
text-align: start;
|
|
2219
2241
|
vertical-align: top;
|
|
2220
2242
|
box-shadow: inset 0 -1px 0 var(--forgebook-separator);
|
|
2243
|
+
overflow-wrap: anywhere;
|
|
2221
2244
|
}
|
|
2222
2245
|
.forgebook-prose th {
|
|
2223
2246
|
font-weight: 600;
|
|
@@ -2261,11 +2284,43 @@
|
|
|
2261
2284
|
font-weight: 600;
|
|
2262
2285
|
color: var(--forgebook-code-name);
|
|
2263
2286
|
}
|
|
2287
|
+
.forgebook-api__head {
|
|
2288
|
+
display: flex;
|
|
2289
|
+
flex-wrap: wrap;
|
|
2290
|
+
align-items: center;
|
|
2291
|
+
justify-content: space-between;
|
|
2292
|
+
gap: 0.5rem 1rem;
|
|
2293
|
+
margin-top: 1rem;
|
|
2294
|
+
}
|
|
2295
|
+
.forgebook-api__head > h2 {
|
|
2296
|
+
margin: 0;
|
|
2297
|
+
font: 700 1.375rem/1.2 var(--forgebook-font-sans);
|
|
2298
|
+
}
|
|
2299
|
+
.forgebook-required-first {
|
|
2300
|
+
display: inline-flex;
|
|
2301
|
+
align-items: center;
|
|
2302
|
+
gap: 0.375rem;
|
|
2303
|
+
font: 400 0.6875rem/1.35 var(--forgebook-font-sans);
|
|
2304
|
+
font-weight: 500;
|
|
2305
|
+
color: var(--forgebook-text-secondary);
|
|
2306
|
+
cursor: pointer;
|
|
2307
|
+
}
|
|
2308
|
+
.forgebook-prop__group {
|
|
2309
|
+
margin-inline: 0.375rem auto;
|
|
2310
|
+
padding: 0 0.375rem;
|
|
2311
|
+
border-radius: 999px;
|
|
2312
|
+
background: var(--forgebook-fill);
|
|
2313
|
+
font: 400 0.6875rem/1.35 var(--forgebook-font-sans);
|
|
2314
|
+
font-weight: 400;
|
|
2315
|
+
color: var(--forgebook-text-secondary);
|
|
2316
|
+
white-space: nowrap;
|
|
2317
|
+
}
|
|
2264
2318
|
.forgebook-api__type {
|
|
2265
2319
|
min-width: 10rem;
|
|
2266
2320
|
}
|
|
2267
2321
|
.forgebook-api__subcomponent {
|
|
2268
2322
|
display: grid;
|
|
2323
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2269
2324
|
gap: 0.75rem;
|
|
2270
2325
|
margin-top: 1rem;
|
|
2271
2326
|
}
|
|
@@ -160,6 +160,8 @@ declare const shellStrings: {
|
|
|
160
160
|
rangeValue: (prop: string) => string;
|
|
161
161
|
setByStory: string;
|
|
162
162
|
required: string;
|
|
163
|
+
requiredFirst: string;
|
|
164
|
+
requiredFirstHint: string;
|
|
163
165
|
resetArgs: string;
|
|
164
166
|
appearance: string;
|
|
165
167
|
appearanceOf: (name: string) => string;
|
|
@@ -127,6 +127,8 @@ const shellStrings = {
|
|
|
127
127
|
rangeValue: (prop) => `${prop}: value`,
|
|
128
128
|
setByStory: "Set by the story",
|
|
129
129
|
required: "Required",
|
|
130
|
+
requiredFirst: "Required first",
|
|
131
|
+
requiredFirstHint: "Every component's required props before the others; kept in this browser",
|
|
130
132
|
resetArgs: "Reset",
|
|
131
133
|
appearance: "Appearance",
|
|
132
134
|
appearanceOf: (name) => `Appearance: ${name}`,
|