@aiaiai-pt/design-system 0.8.2 → 0.8.4
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/components/ValueSourcePicker.svelte +49 -25
- package/package.json +1 -1
- package/tokens/semantic.css +10 -3
|
@@ -81,6 +81,15 @@
|
|
|
81
81
|
"function",
|
|
82
82
|
"expression",
|
|
83
83
|
],
|
|
84
|
+
/**
|
|
85
|
+
* Mode pre-selected when `value === null`, so the operator lands
|
|
86
|
+
* on an editable affordance instead of a "Pick a source"
|
|
87
|
+
* placeholder. The bound `value` stays `null` until the operator
|
|
88
|
+
* interacts — form dirty-tracking and consumer-side null intent
|
|
89
|
+
* survive. The default is forbidden if it isn't in `allowed`.
|
|
90
|
+
* @type {ValueSourceMode | null}
|
|
91
|
+
*/
|
|
92
|
+
defaultMode = null,
|
|
84
93
|
/** @type {ValueSourceContext} */
|
|
85
94
|
context = {},
|
|
86
95
|
/** @type {string | undefined} */
|
|
@@ -137,6 +146,19 @@
|
|
|
137
146
|
currentMode !== null && !allowed.includes(currentMode),
|
|
138
147
|
);
|
|
139
148
|
|
|
149
|
+
// Effective view of the picker — uses `defaultMode` as a fallback
|
|
150
|
+
// when there's no stored value, so the operator sees a mode +
|
|
151
|
+
// affordance pre-selected. Read-only: `value` stays null until the
|
|
152
|
+
// operator interacts. Forbidden defaults silently fall back to the
|
|
153
|
+
// null placeholder rather than rendering a mode that isn't allowed.
|
|
154
|
+
const effectiveValue = $derived.by(() => {
|
|
155
|
+
if (value !== null) return value;
|
|
156
|
+
if (defaultMode === null) return null;
|
|
157
|
+
if (!allowed.includes(defaultMode)) return null;
|
|
158
|
+
return makeBlankForMode(defaultMode);
|
|
159
|
+
});
|
|
160
|
+
const effectiveMode = $derived(effectiveValue?.mode ?? null);
|
|
161
|
+
|
|
140
162
|
function emit(next) {
|
|
141
163
|
value = next;
|
|
142
164
|
onchange?.(next);
|
|
@@ -144,7 +166,9 @@
|
|
|
144
166
|
|
|
145
167
|
function pickMode(/** @type {string} */ next) {
|
|
146
168
|
const mode = /** @type {ValueSourceMode} */ (next);
|
|
147
|
-
|
|
169
|
+
// Compare against the effective mode so re-picking the
|
|
170
|
+
// pre-selected default is a no-op rather than an emit.
|
|
171
|
+
if (mode === effectiveMode) return;
|
|
148
172
|
emit(makeBlankForMode(mode));
|
|
149
173
|
}
|
|
150
174
|
|
|
@@ -374,8 +398,8 @@
|
|
|
374
398
|
<Select
|
|
375
399
|
id={`${groupId}-mode`}
|
|
376
400
|
size="sm"
|
|
377
|
-
placeholder={
|
|
378
|
-
value={
|
|
401
|
+
placeholder={effectiveValue === null ? "Pick a source" : undefined}
|
|
402
|
+
value={effectiveMode ?? ""}
|
|
379
403
|
options={modeOptions}
|
|
380
404
|
onchange={pickMode}
|
|
381
405
|
{disabled}
|
|
@@ -388,90 +412,90 @@
|
|
|
388
412
|
<Badge variant="error">no longer allowed: {MODE_LABEL[value.mode]}</Badge>
|
|
389
413
|
<Button variant="ghost" size="sm" onclick={clear}>Clear</Button>
|
|
390
414
|
</div>
|
|
391
|
-
{:else if
|
|
415
|
+
{:else if effectiveValue === null}
|
|
392
416
|
<span class="vsp-placeholder">{MODE_DESCRIPTION[allowed[0]] ?? ""}</span>
|
|
393
|
-
{:else if
|
|
417
|
+
{:else if effectiveValue.mode === "literal"}
|
|
394
418
|
<Input
|
|
395
419
|
size="sm"
|
|
396
420
|
placeholder={literalPlaceholder(expectedType)}
|
|
397
|
-
value={String(
|
|
421
|
+
value={String(effectiveValue.value ?? "")}
|
|
398
422
|
oninput={(e) => emit({ mode: "literal", value: coerceLiteral(/** @type {HTMLInputElement} */ (e.target).value, expectedType) })}
|
|
399
423
|
{disabled}
|
|
400
424
|
/>
|
|
401
|
-
{:else if
|
|
425
|
+
{:else if effectiveValue.mode === "parameter"}
|
|
402
426
|
<Combobox
|
|
403
427
|
size="sm"
|
|
404
428
|
placeholder="Pick a parameter"
|
|
405
429
|
items={paramOptions()}
|
|
406
|
-
value={
|
|
430
|
+
value={effectiveValue.key}
|
|
407
431
|
onchange={(k) => emit({ mode: "parameter", key: k })}
|
|
408
432
|
{disabled}
|
|
409
433
|
/>
|
|
410
|
-
{:else if
|
|
434
|
+
{:else if effectiveValue.mode === "entity-field"}
|
|
411
435
|
<Combobox
|
|
412
436
|
size="sm"
|
|
413
437
|
placeholder="Pick a field"
|
|
414
438
|
items={entityFieldOptions()}
|
|
415
|
-
value={
|
|
439
|
+
value={effectiveValue.field}
|
|
416
440
|
onchange={(f) => emit({ mode: "entity-field", field: f })}
|
|
417
441
|
{disabled}
|
|
418
442
|
/>
|
|
419
|
-
{:else if
|
|
443
|
+
{:else if effectiveValue.mode === "user-field"}
|
|
420
444
|
<Combobox
|
|
421
445
|
size="sm"
|
|
422
446
|
placeholder="Pick a user claim"
|
|
423
447
|
items={userFieldOptions()}
|
|
424
|
-
value={
|
|
448
|
+
value={effectiveValue.key}
|
|
425
449
|
onchange={(k) => emit({ mode: "user-field", key: k })}
|
|
426
450
|
{disabled}
|
|
427
451
|
/>
|
|
428
|
-
{:else if
|
|
452
|
+
{:else if effectiveValue.mode === "now"}
|
|
429
453
|
<Badge variant="info">$now — current UTC timestamp</Badge>
|
|
430
|
-
{:else if
|
|
454
|
+
{:else if effectiveValue.mode === "source-id"}
|
|
431
455
|
<Badge variant="info">$source.id — id of the entity being acted upon</Badge>
|
|
432
|
-
{:else if
|
|
456
|
+
{:else if effectiveValue.mode === "config-list"}
|
|
433
457
|
<Combobox
|
|
434
458
|
size="sm"
|
|
435
459
|
placeholder="Pick a config type"
|
|
436
460
|
items={configTypeOptions()}
|
|
437
|
-
value={
|
|
461
|
+
value={effectiveValue.configType}
|
|
438
462
|
onchange={(c) => emit({ mode: "config-list", configType: c })}
|
|
439
463
|
{disabled}
|
|
440
464
|
/>
|
|
441
465
|
<Badge variant="neutral">list</Badge>
|
|
442
|
-
{:else if
|
|
466
|
+
{:else if effectiveValue.mode === "expression"}
|
|
443
467
|
<Input
|
|
444
468
|
size="sm"
|
|
445
469
|
placeholder="$entity.X + 1"
|
|
446
|
-
value={
|
|
470
|
+
value={effectiveValue.expr}
|
|
447
471
|
oninput={(e) => emit({ mode: "expression", expr: /** @type {HTMLInputElement} */ (e.target).value })}
|
|
448
472
|
{disabled}
|
|
449
473
|
/>
|
|
450
|
-
{:else if
|
|
474
|
+
{:else if effectiveValue.mode === "created-field"}
|
|
451
475
|
<div class="vsp-inline">
|
|
452
476
|
<Combobox
|
|
453
477
|
size="sm"
|
|
454
478
|
placeholder="prior create"
|
|
455
479
|
items={priorCreateOptions()}
|
|
456
|
-
value={String(
|
|
457
|
-
onchange={(i) => emit({ mode: "created-field", index: Number(i), field:
|
|
480
|
+
value={String(effectiveValue.index)}
|
|
481
|
+
onchange={(i) => emit({ mode: "created-field", index: Number(i), field: /** @type {{mode:'created-field',index:number,field:string}} */ (effectiveValue).field })}
|
|
458
482
|
{disabled}
|
|
459
483
|
/>
|
|
460
484
|
<Combobox
|
|
461
485
|
size="sm"
|
|
462
486
|
placeholder="field"
|
|
463
487
|
items={priorCreateFieldOptions()}
|
|
464
|
-
value={
|
|
465
|
-
onchange={(f) => emit({ mode: "created-field", index:
|
|
488
|
+
value={effectiveValue.field}
|
|
489
|
+
onchange={(f) => emit({ mode: "created-field", index: /** @type {{mode:'created-field',index:number,field:string}} */ (effectiveValue).index, field: f })}
|
|
466
490
|
{disabled}
|
|
467
491
|
/>
|
|
468
492
|
</div>
|
|
469
|
-
{:else if
|
|
493
|
+
{:else if effectiveValue.mode === "function"}
|
|
470
494
|
<Combobox
|
|
471
495
|
size="sm"
|
|
472
496
|
placeholder="Pick a function"
|
|
473
497
|
items={functionOptions()}
|
|
474
|
-
value={
|
|
498
|
+
value={effectiveValue.name}
|
|
475
499
|
onchange={(n) => emit({ mode: "function", name: n, args: {} })}
|
|
476
500
|
{disabled}
|
|
477
501
|
/>
|
package/package.json
CHANGED
package/tokens/semantic.css
CHANGED
|
@@ -97,11 +97,18 @@
|
|
|
97
97
|
--type-body-sm-tracking: var(--raw-tracking-micro);
|
|
98
98
|
--type-body-sm-font: var(--font-sans);
|
|
99
99
|
|
|
100
|
+
/* Form labels (#63 typography). Was uppercase-monospace-light-wider —
|
|
101
|
+
the dev-tool look the action-editor walk flagged as the
|
|
102
|
+
highest-leverage single change. Now sentence-case body sans, medium
|
|
103
|
+
weight, normal tracking. Monospace is reserved for code tokens
|
|
104
|
+
(keys, layout codes, template placeholders), NOT labels. Consumers
|
|
105
|
+
should pass labels as `"Field name"`, not `"FIELD NAME"`. See
|
|
106
|
+
dev_docs/specs/typography-form-labels.md (ADR). */
|
|
100
107
|
--type-label-size: var(--raw-font-size-12);
|
|
101
|
-
--type-label-weight: var(--raw-font-weight-
|
|
108
|
+
--type-label-weight: var(--raw-font-weight-medium);
|
|
102
109
|
--type-label-leading: var(--raw-line-height-heading);
|
|
103
|
-
--type-label-tracking: var(--raw-tracking-
|
|
104
|
-
--type-label-font: var(--font-
|
|
110
|
+
--type-label-tracking: var(--raw-tracking-normal);
|
|
111
|
+
--type-label-font: var(--font-sans);
|
|
105
112
|
|
|
106
113
|
--type-data-size: var(--raw-font-size-14);
|
|
107
114
|
--type-data-weight: var(--raw-font-weight-regular);
|