@motion-proto/live-tokens 0.3.9 → 0.5.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/package.json +9 -8
- package/src/component-editor/BadgeEditor.svelte +24 -22
- package/src/component-editor/CalloutEditor.svelte +3 -3
- package/src/component-editor/CardEditor.svelte +25 -21
- package/src/component-editor/CollapsibleSectionEditor.svelte +27 -25
- package/src/component-editor/CornerBadgeEditor.svelte +37 -35
- package/src/component-editor/DialogEditor.svelte +26 -24
- package/src/component-editor/ImageEditor.svelte +11 -9
- package/src/component-editor/InlineEditActionsEditor.svelte +17 -15
- package/src/component-editor/NotificationEditor.svelte +32 -30
- package/src/component-editor/ProgressBarEditor.svelte +3 -3
- package/src/component-editor/RadioButtonEditor.svelte +31 -29
- package/src/component-editor/SectionDividerEditor.svelte +30 -28
- package/src/component-editor/SegmentedControlEditor.svelte +29 -25
- package/src/component-editor/StandardButtonsEditor.svelte +42 -38
- package/src/component-editor/TabBarEditor.svelte +20 -18
- package/src/component-editor/TableEditor.svelte +4 -4
- package/src/component-editor/TooltipEditor.svelte +11 -9
- package/src/component-editor/registry.ts +2 -2
- package/src/component-editor/scaffolding/AngleDial.svelte +20 -19
- package/src/component-editor/scaffolding/ComponentEditorBase.svelte +44 -20
- package/src/component-editor/scaffolding/ComponentFileManager.svelte +260 -37
- package/src/component-editor/scaffolding/ComponentFileMenu.svelte +41 -29
- package/src/component-editor/scaffolding/ComponentsTab.svelte +7 -3
- package/src/component-editor/scaffolding/CopyFromMenu.svelte +21 -12
- package/src/component-editor/scaffolding/DemoHeader.svelte +13 -4
- package/src/component-editor/scaffolding/DividerEditor.svelte +27 -14
- package/src/component-editor/scaffolding/FieldsetWrapper.svelte +10 -4
- package/src/component-editor/scaffolding/GradientCard.svelte +25 -20
- package/src/component-editor/scaffolding/LinkageChart.svelte +43 -34
- package/src/component-editor/scaffolding/LinkedBlock.svelte +24 -21
- package/src/component-editor/scaffolding/NonStylableConfig.svelte +6 -1
- package/src/component-editor/scaffolding/SaveAsDialog.svelte +39 -35
- package/src/component-editor/scaffolding/ShadowBackdrop.svelte +21 -9
- package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +8 -3
- package/src/component-editor/scaffolding/StateBlock.svelte +30 -13
- package/src/component-editor/scaffolding/TokenLayout.svelte +46 -30
- package/src/component-editor/scaffolding/TypeEditor.svelte +52 -26
- package/src/component-editor/scaffolding/VariantGroup.svelte +81 -48
- package/src/component-editor/scaffolding/componentSectionType.ts +2 -2
- package/src/components/Badge.svelte +45 -26
- package/src/components/Button.svelte +44 -21
- package/src/components/Callout.svelte +17 -12
- package/src/components/Card.svelte +23 -11
- package/src/components/CollapsibleSection.svelte +56 -27
- package/src/components/CornerBadge.svelte +32 -18
- package/src/components/Dialog.svelte +55 -31
- package/src/components/Image.svelte +14 -5
- package/src/components/InlineEditActions.svelte +22 -10
- package/src/components/Notification.svelte +39 -19
- package/src/components/ProgressBar.svelte +27 -17
- package/src/components/RadioButton.svelte +27 -10
- package/src/components/SectionDivider.svelte +34 -26
- package/src/components/SegmentedControl.svelte +23 -9
- package/src/components/TabBar.svelte +23 -10
- package/src/components/Table.svelte +8 -3
- package/src/components/Tooltip.svelte +15 -5
- package/src/lib/ColumnsOverlay.svelte +3 -3
- package/src/lib/LiveEditorOverlay.svelte +57 -36
- package/src/pages/ComponentEditorPage.svelte +17 -13
- package/src/pages/EditorShell.svelte +24 -20
- package/src/styles/form-controls.css +2 -2
- package/src/styles/tokens.css +59 -81
- package/src/ui/BezierCurveEditor.svelte +59 -43
- package/src/ui/ColorEditPanel.svelte +71 -44
- package/src/ui/EditorViewSwitcher.svelte +9 -5
- package/src/ui/FontStackEditor.svelte +16 -15
- package/src/ui/GradientEditor.svelte +42 -33
- package/src/ui/GradientStopPicker.svelte +18 -29
- package/src/ui/PaletteEditor.svelte +238 -212
- package/src/ui/PresetFileManager.svelte +20 -18
- package/src/ui/ProjectFontsSection.svelte +30 -30
- package/src/ui/SurfacesTab.svelte +3 -3
- package/src/ui/TextTab.svelte +2 -2
- package/src/ui/ThemeFileManager.svelte +38 -35
- package/src/ui/Toggle.svelte +11 -9
- package/src/ui/UICopyPopover.svelte +19 -15
- package/src/ui/UIDialog.svelte +48 -30
- package/src/ui/UIFontFamilySelector.svelte +104 -78
- package/src/ui/UIFontSizeSelector.svelte +38 -20
- package/src/ui/UIFontWeightSelector.svelte +33 -13
- package/src/ui/UILineHeightSelector.svelte +33 -13
- package/src/ui/UILinkToggle.svelte +7 -6
- package/src/ui/UIOptionItem.svelte +21 -7
- package/src/ui/UIOptionList.svelte +9 -3
- package/src/ui/UIPaddingSelector.svelte +108 -82
- package/src/ui/UIPaletteSelector.svelte +186 -161
- package/src/ui/UIRadio.svelte +23 -8
- package/src/ui/UIRadioGroup.svelte +9 -8
- package/src/ui/UIRelinkConfirmPopover.svelte +26 -16
- package/src/ui/UITokenSelector.svelte +112 -68
- package/src/ui/UIVariantSelector.svelte +79 -57
- package/src/ui/VariablesTab.svelte +15 -15
- package/src/ui/palette/GradientStopEditor.svelte +45 -26
- package/src/ui/palette/OverridesPanel.svelte +85 -49
- package/src/ui/palette/PaletteBase.svelte +60 -32
- package/src/ui/palette/ScaleCurveEditor.svelte +25 -10
- package/src/ui/sections/ColumnsSection.svelte +13 -13
- package/src/ui/sections/GradientsSection.svelte +12 -9
- package/src/ui/sections/OverlaysSection.svelte +50 -47
- package/src/ui/sections/ShadowsSection.svelte +110 -104
- package/src/ui/sections/TokenScaleTable.svelte +38 -22
- package/src/ui/sections/tokenScales.ts +2 -2
|
@@ -1,43 +1,26 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { run } from 'svelte/legacy';
|
|
3
|
+
|
|
3
4
|
import type { ComponentConfigMeta } from '../../lib/themeTypes';
|
|
4
5
|
import { sanitizeFileName } from '../../lib/themeService';
|
|
5
6
|
import UIDialog from '../../ui/UIDialog.svelte';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
interface Props {
|
|
9
|
+
/** Two-way bound: parent toggles to open/close. */
|
|
10
|
+
show?: boolean;
|
|
11
|
+
/** Display name to seed the input with when the dialog opens. */
|
|
12
|
+
currentDisplayName?: string;
|
|
13
|
+
/** Existing files used by the increment helper to find the next available `_NN` suffix. */
|
|
14
|
+
files?: ComponentConfigMeta[];
|
|
15
|
+
onsave?: (payload: { displayName: string; fileName: string }) => void;
|
|
16
|
+
}
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
save: { displayName: string; fileName: string };
|
|
16
|
-
}>();
|
|
18
|
+
let { show = $bindable(false), currentDisplayName = '', files = [], onsave }: Props = $props();
|
|
17
19
|
|
|
18
|
-
let saveAsName = '';
|
|
19
|
-
let saveAsInput: HTMLInputElement;
|
|
20
|
+
let saveAsName = $state('');
|
|
21
|
+
let saveAsInput: HTMLInputElement | undefined = $state();
|
|
20
22
|
|
|
21
|
-
// Seed and select the input whenever the dialog opens. setTimeout(..., 0)
|
|
22
|
-
// matches the original parent's behaviour: it runs as a macrotask, after
|
|
23
|
-
// UIDialog's microtask-queued focus on the confirm button — so the input
|
|
24
|
-
// ends up focused-and-selected, not the button.
|
|
25
|
-
$: if (show) {
|
|
26
|
-
saveAsName =
|
|
27
|
-
sanitizeFileName(currentDisplayName) === 'default'
|
|
28
|
-
? nextIncrementName(currentDisplayName).displayName
|
|
29
|
-
: currentDisplayName;
|
|
30
|
-
setTimeout(() => saveAsInput?.select(), 0);
|
|
31
|
-
}
|
|
32
23
|
|
|
33
|
-
$: saveAsError = (() => {
|
|
34
|
-
const trimmed = saveAsName.trim();
|
|
35
|
-
if (!trimmed) return '';
|
|
36
|
-
if (sanitizeFileName(trimmed) === 'default') {
|
|
37
|
-
return 'The name "default" is reserved for the core component definition.';
|
|
38
|
-
}
|
|
39
|
-
return '';
|
|
40
|
-
})();
|
|
41
24
|
|
|
42
25
|
function nextIncrementName(baseDisplay: string): { displayName: string; fileName: string } {
|
|
43
26
|
const baseName = baseDisplay.replace(/_\d+$/, '');
|
|
@@ -67,12 +50,33 @@
|
|
|
67
50
|
if (!displayName || saveAsError) return;
|
|
68
51
|
const fileName = sanitizeFileName(displayName);
|
|
69
52
|
show = false;
|
|
70
|
-
|
|
53
|
+
onsave?.({ displayName, fileName });
|
|
71
54
|
}
|
|
72
55
|
|
|
73
56
|
function handleKeydown(e: KeyboardEvent) {
|
|
74
57
|
if (e.key === 'Enter') confirmSaveAs();
|
|
75
58
|
}
|
|
59
|
+
// Seed and select the input whenever the dialog opens. setTimeout(..., 0)
|
|
60
|
+
// matches the original parent's behaviour: it runs as a macrotask, after
|
|
61
|
+
// UIDialog's microtask-queued focus on the confirm button — so the input
|
|
62
|
+
// ends up focused-and-selected, not the button.
|
|
63
|
+
run(() => {
|
|
64
|
+
if (show) {
|
|
65
|
+
saveAsName =
|
|
66
|
+
sanitizeFileName(currentDisplayName) === 'default'
|
|
67
|
+
? nextIncrementName(currentDisplayName).displayName
|
|
68
|
+
: currentDisplayName;
|
|
69
|
+
setTimeout(() => saveAsInput?.select(), 0);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
let saveAsError = $derived((() => {
|
|
73
|
+
const trimmed = saveAsName.trim();
|
|
74
|
+
if (!trimmed) return '';
|
|
75
|
+
if (sanitizeFileName(trimmed) === 'default') {
|
|
76
|
+
return 'The name "default" is reserved for the core component definition.';
|
|
77
|
+
}
|
|
78
|
+
return '';
|
|
79
|
+
})());
|
|
76
80
|
</script>
|
|
77
81
|
|
|
78
82
|
<UIDialog
|
|
@@ -81,7 +85,7 @@
|
|
|
81
85
|
cancelLabel="Cancel"
|
|
82
86
|
confirmLabel="Save"
|
|
83
87
|
confirmDisabled={!saveAsName.trim() || !!saveAsError}
|
|
84
|
-
|
|
88
|
+
onconfirm={confirmSaveAs}
|
|
85
89
|
width="360px"
|
|
86
90
|
>
|
|
87
91
|
<div class="save-as-dialog">
|
|
@@ -92,13 +96,13 @@
|
|
|
92
96
|
type="text"
|
|
93
97
|
bind:value={saveAsName}
|
|
94
98
|
bind:this={saveAsInput}
|
|
95
|
-
|
|
99
|
+
onkeydown={handleKeydown}
|
|
96
100
|
placeholder="Config name…"
|
|
97
101
|
/>
|
|
98
102
|
<button
|
|
99
103
|
type="button"
|
|
100
104
|
class="save-as-increment"
|
|
101
|
-
|
|
105
|
+
onclick={incrementSaveAsName}
|
|
102
106
|
title="Increment filename"
|
|
103
107
|
>
|
|
104
108
|
<i class="fas fa-plus"></i>
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import newspaperBg from '../../assets/newspaper.webp';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
mode?: 'image' | 'color';
|
|
8
|
+
/** CSS var name (set by ShadowBackdropControls) the backdrop reads when in color mode. */
|
|
9
|
+
colorVariable: string;
|
|
10
|
+
/** Padding around the slotted preview. Set to '0' when the slotted component should cover the full backdrop area (e.g. dialog overlay). */
|
|
11
|
+
padding?: string;
|
|
12
|
+
children?: import('svelte').Snippet;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let {
|
|
16
|
+
mode = 'image',
|
|
17
|
+
colorVariable,
|
|
18
|
+
padding = '128px',
|
|
19
|
+
children
|
|
20
|
+
}: Props = $props();
|
|
9
21
|
|
|
10
|
-
|
|
11
|
-
mode === 'image'
|
|
22
|
+
let backgroundStyle =
|
|
23
|
+
$derived(mode === 'image'
|
|
12
24
|
? `padding: ${padding}; background-image: url(${newspaperBg}); background-size: cover; background-position: center; background-repeat: no-repeat;`
|
|
13
|
-
: `padding: ${padding}; background: var(${colorVariable}, #1a1a1a)
|
|
25
|
+
: `padding: ${padding}; background: var(${colorVariable}, #1a1a1a);`);
|
|
14
26
|
</script>
|
|
15
27
|
|
|
16
28
|
<div class="shadow-backdrop" style={backgroundStyle}>
|
|
17
|
-
|
|
29
|
+
{@render children?.()}
|
|
18
30
|
</div>
|
|
19
31
|
|
|
20
32
|
<style>
|
|
@@ -5,9 +5,14 @@
|
|
|
5
5
|
import { setCssVar } from '../../lib/cssVarSync';
|
|
6
6
|
|
|
7
7
|
type Mode = 'image' | 'color';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
mode?: Mode;
|
|
11
|
+
/** Editor-scoped CSS var the picker writes to (must end with `-surface` to allow gradients). */
|
|
12
|
+
colorVariable: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { mode = $bindable('image'), colorVariable }: Props = $props();
|
|
11
16
|
|
|
12
17
|
const options: ReadonlyArray<{ value: Mode; label: string }> = [
|
|
13
18
|
{ value: 'image', label: 'Image' },
|
|
@@ -12,21 +12,38 @@
|
|
|
12
12
|
import TypeEditor from './TypeEditor.svelte';
|
|
13
13
|
import type { Token, TypeGroupConfig } from './types';
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
/** Tokens for this state, fed to `<TokenLayout>`. */
|
|
22
|
+
tokens: Token[];
|
|
23
|
+
/** Type groups for this state; rendered as a row of `<TypeEditor>` blocks. */
|
|
24
|
+
typeGroups?: TypeGroupConfig[];
|
|
25
|
+
/** Forwarded to TypeEditor and TokenLayout so writes persist through the editor store. */
|
|
26
|
+
component?: string | undefined;
|
|
27
|
+
/** Per-variable rank passed through to TokenLayout for linked-block alignment. */
|
|
28
|
+
linkedOrder?: Map<string, number> | undefined;
|
|
29
|
+
/** Render the token grid with N visual columns. >1 spreads a long property
|
|
24
30
|
list horizontally; only meaningful for state-blocks without typeGroups
|
|
25
31
|
(the two-col flex layout already partitions screen real estate when
|
|
26
32
|
typeGroups are present). */
|
|
27
|
-
|
|
33
|
+
columns?: number;
|
|
34
|
+
onchange?: () => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let {
|
|
38
|
+
tokens,
|
|
39
|
+
typeGroups = [],
|
|
40
|
+
component = undefined,
|
|
41
|
+
linkedOrder = undefined,
|
|
42
|
+
columns = 1,
|
|
43
|
+
onchange,
|
|
44
|
+
}: Props = $props();
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
let hasTypeGroups = $derived(typeGroups.length > 0);
|
|
30
47
|
</script>
|
|
31
48
|
|
|
32
49
|
<div class="state-controls" class:two-col={hasTypeGroups}>
|
|
@@ -50,7 +67,7 @@
|
|
|
50
67
|
outlineColorVariable={tg.outlineColorVariable}
|
|
51
68
|
outlineColorLabel={tg.outlineColorLabel ?? 'outline color'}
|
|
52
69
|
{component}
|
|
53
|
-
|
|
70
|
+
{onchange}
|
|
54
71
|
/>
|
|
55
72
|
{/each}
|
|
56
73
|
</div>
|
|
@@ -61,7 +78,7 @@
|
|
|
61
78
|
{component}
|
|
62
79
|
{linkedOrder}
|
|
63
80
|
{columns}
|
|
64
|
-
|
|
81
|
+
{onchange}
|
|
65
82
|
/>
|
|
66
83
|
</div>
|
|
67
84
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import type { Component } from 'svelte';
|
|
3
3
|
import UIPaletteSelector from '../../ui/UIPaletteSelector.svelte';
|
|
4
4
|
import UIVariantSelector from '../../ui/UIVariantSelector.svelte';
|
|
5
5
|
import UIFontFamilySelector from '../../ui/UIFontFamilySelector.svelte';
|
|
@@ -40,21 +40,40 @@
|
|
|
40
40
|
|
|
41
41
|
type Entry = { kind: Kind; token: Token };
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
interface Props {
|
|
49
|
+
title?: string;
|
|
50
|
+
tokens: Token[];
|
|
51
|
+
/** Forwarded to each selector; when set, writes persist through the editor store. */
|
|
52
|
+
component?: string | undefined;
|
|
53
|
+
/** Optional context labels per variable (shown below the selector). */
|
|
54
|
+
contexts?: Record<string, string[]>;
|
|
55
|
+
/** Per-variable rank that overrides kind rank when sorting; lets linked tokens align with the top linked row. */
|
|
56
|
+
linkedOrder?: Map<string, number> | undefined;
|
|
57
|
+
/** Set true on the linked-block instance so dimmed variant rows can scroll/flash to the matching anchor. */
|
|
58
|
+
isLinkedBlock?: boolean;
|
|
59
|
+
/** Number of visual columns. >1 switches to a column-major grid (grid-auto-flow: column)
|
|
54
60
|
so the consumer can spread a long property list across the available width. In
|
|
55
61
|
multi-col mode, the linked-first sort + zone divider are dropped — kind-grouped flow
|
|
56
62
|
reads more naturally when columns themselves carry the visual grouping. */
|
|
57
|
-
|
|
63
|
+
columns?: number;
|
|
64
|
+
onchange?: () => void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let {
|
|
68
|
+
title = '',
|
|
69
|
+
tokens,
|
|
70
|
+
component = undefined,
|
|
71
|
+
contexts = {},
|
|
72
|
+
linkedOrder = undefined,
|
|
73
|
+
isLinkedBlock = false,
|
|
74
|
+
columns = 1,
|
|
75
|
+
onchange,
|
|
76
|
+
}: Props = $props();
|
|
58
77
|
|
|
59
78
|
/** Suffix/prefix patterns mapped to kinds — single source of truth used by `categorize`.
|
|
60
79
|
Order matters: `text` must run before `border`/`surface` because `--text-*` would
|
|
@@ -134,7 +153,7 @@
|
|
|
134
153
|
/** Selector registry: one entry per kind. `extra` props (e.g. UIPaddingSelector's
|
|
135
154
|
`mode`/`splittable`/`rowLabel`) are forwarded alongside the linked props. */
|
|
136
155
|
type SelectorEntry = {
|
|
137
|
-
component:
|
|
156
|
+
component: Component<any, any, any>;
|
|
138
157
|
extra?: (token: Token) => Record<string, unknown>;
|
|
139
158
|
/** When true, the row is rendered as a self-contained block (spans all grid columns,
|
|
140
159
|
no .token-row wrapper, no contexts strip). Currently only `padding-split`. */
|
|
@@ -235,8 +254,6 @@
|
|
|
235
254
|
return set;
|
|
236
255
|
}
|
|
237
256
|
|
|
238
|
-
const dispatch = createEventDispatcher();
|
|
239
|
-
|
|
240
257
|
/** When a row collapses several groupKey leads into one display, mirror the lead's
|
|
241
258
|
new alias onto each peer (and its siblings) so the merged display stays in sync. */
|
|
242
259
|
function handleRowChange(token: Token) {
|
|
@@ -248,7 +265,7 @@
|
|
|
248
265
|
else clearComponentAliasLinked(component, peer);
|
|
249
266
|
}
|
|
250
267
|
}
|
|
251
|
-
|
|
268
|
+
onchange?.();
|
|
252
269
|
}
|
|
253
270
|
|
|
254
271
|
/** Bidirectional hover cue with the Linked-properties block. The upper grid
|
|
@@ -263,20 +280,20 @@
|
|
|
263
280
|
hoveredLinkedVariable?.set(variable);
|
|
264
281
|
}
|
|
265
282
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
283
|
+
let hoveredVar = $derived(!isLinkedBlock && hoveredLinkedVariable ? $hoveredLinkedVariable : null);
|
|
284
|
+
let isMultiCol = $derived(columns > 1);
|
|
285
|
+
let linkedKinds = $derived(computeLinkedKinds(component, $editorState));
|
|
286
|
+
let entries = $derived(buildEntries(tokens.filter((t) => !t.hidden), linkedOrder, linkedKinds, component, $editorState, isMultiCol));
|
|
270
287
|
/** Index of the first independent (non-linked) entry; -1 when there are no linked entries or no boundary.
|
|
271
288
|
Suppressed in multi-col mode (no divider — column structure is the grouping). */
|
|
272
|
-
|
|
289
|
+
let firstIndependentIdx = $derived((() => {
|
|
273
290
|
if (isMultiCol) return -1;
|
|
274
291
|
const idx = entries.findIndex((e) => !linkedKinds.has(e.kind));
|
|
275
292
|
if (idx <= 0) return -1;
|
|
276
293
|
return idx;
|
|
277
|
-
})();
|
|
294
|
+
})());
|
|
278
295
|
/** Rows per column for column-major flow; ceil so the last column may be short. */
|
|
279
|
-
|
|
296
|
+
let rowsPerCol = $derived(isMultiCol ? Math.max(1, Math.ceil(entries.length / columns)) : entries.length);
|
|
280
297
|
|
|
281
298
|
</script>
|
|
282
299
|
|
|
@@ -320,24 +337,23 @@
|
|
|
320
337
|
-->
|
|
321
338
|
{@const isLinkedRow = linkedKinds.has(entry.kind)}
|
|
322
339
|
{@const isHovered = !isLinkedBlock && isLinkedRow && hoveredVar === token.variable}
|
|
323
|
-
<!-- svelte-ignore
|
|
340
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
324
341
|
<div
|
|
325
342
|
class="token-entry"
|
|
326
343
|
class:token-row={!sel.standalone}
|
|
327
344
|
class:has-contexts={!sel.standalone && !!ctxs?.length}
|
|
328
345
|
class:linked-hovered={isHovered}
|
|
329
346
|
class:non-first-set={isNonFirstSet}
|
|
330
|
-
|
|
331
|
-
|
|
347
|
+
onmouseenter={isLinkedBlock || !isLinkedRow ? undefined : () => setHover(token.variable)}
|
|
348
|
+
onmouseleave={isLinkedBlock || !isLinkedRow ? undefined : () => setHover(null)}
|
|
332
349
|
>
|
|
333
350
|
{#if !sel.standalone}
|
|
334
351
|
<span class="token-label">{token.label}</span>
|
|
335
352
|
{/if}
|
|
336
|
-
<
|
|
337
|
-
this={sel.component}
|
|
353
|
+
<sel.component
|
|
338
354
|
{...sharedProps}
|
|
339
355
|
{...extra}
|
|
340
|
-
|
|
356
|
+
onchange={() => handleRowChange(token)}
|
|
341
357
|
/>
|
|
342
358
|
{#if !sel.standalone && ctxs?.length}
|
|
343
359
|
<div class="token-contexts">
|
|
@@ -8,57 +8,83 @@
|
|
|
8
8
|
import FieldsetWrapper from './FieldsetWrapper.svelte';
|
|
9
9
|
import { BORDER_WIDTH } from '../../ui/variantScales';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
colorVariable: string;
|
|
16
|
+
colorLabel?: string;
|
|
17
|
+
familyVariable?: string | undefined;
|
|
18
|
+
familyLabel?: string;
|
|
19
|
+
sizeVariable?: string | undefined;
|
|
20
|
+
sizeLabel?: string;
|
|
21
|
+
weightVariable?: string | undefined;
|
|
22
|
+
weightLabel?: string;
|
|
23
|
+
lineHeightVariable?: string | undefined;
|
|
24
|
+
lineHeightLabel?: string;
|
|
25
|
+
/** Optional outline rows rendered under the typography rows so a text-with-
|
|
22
26
|
stroke group keeps stroke controls visually nested with the type they
|
|
23
27
|
drive (e.g. SectionDivider title outline). */
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
outlineWidthVariable?: string | undefined;
|
|
29
|
+
outlineWidthLabel?: string;
|
|
30
|
+
outlineColorVariable?: string | undefined;
|
|
31
|
+
outlineColorLabel?: string;
|
|
32
|
+
/** When set, writes persist through the editor store under this component. */
|
|
33
|
+
component?: string | undefined;
|
|
34
|
+
/** Legend text for the fieldset. */
|
|
35
|
+
legend?: string;
|
|
36
|
+
onchange?: () => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let {
|
|
40
|
+
colorVariable,
|
|
41
|
+
colorLabel = 'color',
|
|
42
|
+
familyVariable = undefined,
|
|
43
|
+
familyLabel = 'family',
|
|
44
|
+
sizeVariable = undefined,
|
|
45
|
+
sizeLabel = 'size',
|
|
46
|
+
weightVariable = undefined,
|
|
47
|
+
weightLabel = 'weight',
|
|
48
|
+
lineHeightVariable = undefined,
|
|
49
|
+
lineHeightLabel = 'line-h',
|
|
50
|
+
outlineWidthVariable = undefined,
|
|
51
|
+
outlineWidthLabel = 'outline thickness',
|
|
52
|
+
outlineColorVariable = undefined,
|
|
53
|
+
outlineColorLabel = 'outline color',
|
|
54
|
+
component = undefined,
|
|
55
|
+
legend = 'type',
|
|
56
|
+
onchange,
|
|
57
|
+
}: Props = $props();
|
|
32
58
|
</script>
|
|
33
59
|
|
|
34
60
|
<FieldsetWrapper {legend}>
|
|
35
61
|
<div class="type-grid">
|
|
36
62
|
<span class="row-label">{colorLabel}</span>
|
|
37
|
-
<UIPaletteSelector variable={colorVariable} {component}
|
|
63
|
+
<UIPaletteSelector variable={colorVariable} {component} {onchange} />
|
|
38
64
|
|
|
39
65
|
{#if familyVariable}
|
|
40
66
|
<span class="row-label">{familyLabel}</span>
|
|
41
|
-
<UIFontFamilySelector variable={familyVariable} {component} canBeLinked
|
|
67
|
+
<UIFontFamilySelector variable={familyVariable} {component} canBeLinked {onchange} />
|
|
42
68
|
{/if}
|
|
43
69
|
{#if weightVariable}
|
|
44
70
|
<span class="row-label">{weightLabel}</span>
|
|
45
|
-
<UIFontWeightSelector variable={weightVariable} {component} canBeLinked
|
|
71
|
+
<UIFontWeightSelector variable={weightVariable} {component} canBeLinked {onchange} />
|
|
46
72
|
{/if}
|
|
47
73
|
{#if sizeVariable}
|
|
48
74
|
<span class="row-label">{sizeLabel}</span>
|
|
49
|
-
<UIFontSizeSelector variable={sizeVariable} {component} canBeLinked
|
|
75
|
+
<UIFontSizeSelector variable={sizeVariable} {component} canBeLinked {onchange} />
|
|
50
76
|
{/if}
|
|
51
77
|
{#if lineHeightVariable}
|
|
52
78
|
<span class="row-label">{lineHeightLabel}</span>
|
|
53
|
-
<UILineHeightSelector variable={lineHeightVariable} {component} canBeLinked
|
|
79
|
+
<UILineHeightSelector variable={lineHeightVariable} {component} canBeLinked {onchange} />
|
|
54
80
|
{/if}
|
|
55
81
|
{#if outlineWidthVariable}
|
|
56
82
|
<span class="row-label">{outlineWidthLabel}</span>
|
|
57
|
-
<UIVariantSelector variable={outlineWidthVariable} {component} canBeLinked {...BORDER_WIDTH}
|
|
83
|
+
<UIVariantSelector variable={outlineWidthVariable} {component} canBeLinked {...BORDER_WIDTH} {onchange} />
|
|
58
84
|
{/if}
|
|
59
85
|
{#if outlineColorVariable}
|
|
60
86
|
<span class="row-label">{outlineColorLabel}</span>
|
|
61
|
-
<UIPaletteSelector variable={outlineColorVariable} {component} canBeLinked
|
|
87
|
+
<UIPaletteSelector variable={outlineColorVariable} {component} canBeLinked {onchange} />
|
|
62
88
|
{/if}
|
|
63
89
|
</div>
|
|
64
90
|
</FieldsetWrapper>
|