@aiaiai-pt/design-system 0.8.3 → 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.
@@ -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
- if (mode === currentMode) return;
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={value === null ? "Pick a source" : undefined}
378
- value={currentMode ?? ""}
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 value === null}
415
+ {:else if effectiveValue === null}
392
416
  <span class="vsp-placeholder">{MODE_DESCRIPTION[allowed[0]] ?? ""}</span>
393
- {:else if value.mode === "literal"}
417
+ {:else if effectiveValue.mode === "literal"}
394
418
  <Input
395
419
  size="sm"
396
420
  placeholder={literalPlaceholder(expectedType)}
397
- value={String(value.value ?? "")}
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 value.mode === "parameter"}
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={value.key}
430
+ value={effectiveValue.key}
407
431
  onchange={(k) => emit({ mode: "parameter", key: k })}
408
432
  {disabled}
409
433
  />
410
- {:else if value.mode === "entity-field"}
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={value.field}
439
+ value={effectiveValue.field}
416
440
  onchange={(f) => emit({ mode: "entity-field", field: f })}
417
441
  {disabled}
418
442
  />
419
- {:else if value.mode === "user-field"}
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={value.key}
448
+ value={effectiveValue.key}
425
449
  onchange={(k) => emit({ mode: "user-field", key: k })}
426
450
  {disabled}
427
451
  />
428
- {:else if value.mode === "now"}
452
+ {:else if effectiveValue.mode === "now"}
429
453
  <Badge variant="info">$now — current UTC timestamp</Badge>
430
- {:else if value.mode === "source-id"}
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 value.mode === "config-list"}
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={value.configType}
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 value.mode === "expression"}
466
+ {:else if effectiveValue.mode === "expression"}
443
467
  <Input
444
468
  size="sm"
445
469
  placeholder="$entity.X + 1"
446
- value={value.expr}
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 value.mode === "created-field"}
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(value.index)}
457
- onchange={(i) => emit({ mode: "created-field", index: Number(i), field: value.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={value.field}
465
- onchange={(f) => emit({ mode: "created-field", index: value.index, field: f })}
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 value.mode === "function"}
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={value.name}
498
+ value={effectiveValue.name}
475
499
  onchange={(n) => emit({ mode: "function", name: n, args: {} })}
476
500
  {disabled}
477
501
  />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiaiai-pt/design-system",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Design system tokens and Svelte components for aiaiai products",
5
5
  "license": "MIT",
6
6
  "type": "module",