@pure-ds/core 0.6.8 → 0.6.10

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.
Files changed (42) hide show
  1. package/custom-elements.json +71 -28
  2. package/dist/types/pds.d.ts +30 -0
  3. package/dist/types/public/assets/js/pds-manager.d.ts +146 -429
  4. package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -1
  5. package/dist/types/public/assets/js/pds.d.ts +3 -4
  6. package/dist/types/public/assets/js/pds.d.ts.map +1 -1
  7. package/dist/types/public/assets/pds/components/pds-form.d.ts.map +1 -1
  8. package/dist/types/public/assets/pds/components/pds-live-edit.d.ts +1 -169
  9. package/dist/types/public/assets/pds/components/pds-live-edit.d.ts.map +1 -1
  10. package/dist/types/public/assets/pds/components/pds-omnibox.d.ts +0 -2
  11. package/dist/types/public/assets/pds/components/pds-omnibox.d.ts.map +1 -1
  12. package/dist/types/src/js/pds-core/pds-config.d.ts +1306 -13
  13. package/dist/types/src/js/pds-core/pds-config.d.ts.map +1 -1
  14. package/dist/types/src/js/pds-core/pds-enhancers-meta.d.ts.map +1 -1
  15. package/dist/types/src/js/pds-core/pds-enhancers.d.ts.map +1 -1
  16. package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -1
  17. package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -1
  18. package/dist/types/src/js/pds-core/pds-ontology.d.ts.map +1 -1
  19. package/dist/types/src/js/pds-core/pds-start-helpers.d.ts +1 -4
  20. package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -1
  21. package/dist/types/src/js/pds-manager.d.ts +1 -0
  22. package/dist/types/src/js/pds.d.ts.map +1 -1
  23. package/package.json +2 -2
  24. package/packages/pds-cli/bin/pds-static.js +16 -1
  25. package/public/assets/js/app.js +21 -21
  26. package/public/assets/js/pds-manager.js +291 -161
  27. package/public/assets/js/pds.js +16 -16
  28. package/public/assets/pds/components/pds-form.js +124 -27
  29. package/public/assets/pds/components/pds-live-edit.js +1214 -104
  30. package/public/assets/pds/components/pds-omnibox.js +10 -18
  31. package/public/assets/pds/custom-elements.json +71 -28
  32. package/public/assets/pds/pds-css-complete.json +1 -6
  33. package/public/assets/pds/pds.css-data.json +5 -35
  34. package/src/js/pds-core/pds-config.js +822 -31
  35. package/src/js/pds-core/pds-enhancers-meta.js +11 -0
  36. package/src/js/pds-core/pds-enhancers.js +113 -5
  37. package/src/js/pds-core/pds-generator.js +183 -23
  38. package/src/js/pds-core/pds-live.js +177 -2
  39. package/src/js/pds-core/pds-ontology.js +6 -0
  40. package/src/js/pds-core/pds-start-helpers.js +14 -6
  41. package/src/js/pds.d.ts +30 -0
  42. package/src/js/pds.js +36 -60
@@ -23,6 +23,7 @@ const DEFAULT_OPTIONS = {
23
23
  icons: true, // Enable icon-enhanced inputs
24
24
  datalists: true, // Enable datalist autocomplete
25
25
  rangeOutput: true, // Use .range-output for ranges
26
+ colorInput: true, // Use label[data-color] enhancement for color widgets
26
27
  },
27
28
  validation: {
28
29
  showErrors: true, // Show validation errors inline
@@ -836,7 +837,11 @@ export class SchemaForm extends LitElement {
836
837
  ${!this.hideLegend && !context.hideLegend
837
838
  ? html`<legend>${legend}</legend>`
838
839
  : nothing}
839
- ${node.children.map((child) => this.#renderNode(child, context))}
840
+ ${node.children.map((child) =>
841
+ this.#renderNode(
842
+ child,
843
+ context?.hideLegend ? { ...context, hideLegend: false } : context
844
+ ))}
840
845
  </fieldset>
841
846
  `;
842
847
 
@@ -1144,25 +1149,35 @@ export class SchemaForm extends LitElement {
1144
1149
  const ui = node.ui || this.#uiFor(path);
1145
1150
  const itemSchema = node.item?.schema;
1146
1151
 
1147
- // Check if this is a simple string array that should use the open group enhancement
1148
- const isSimpleStringArray =
1149
- itemSchema?.type === "string" &&
1150
- !itemSchema.format &&
1151
- !itemSchema.enum &&
1152
- (!itemSchema.maxLength || itemSchema.maxLength <= 100);
1152
+ const primitiveArrayTypes = new Set(["string", "number", "integer", "boolean"]);
1153
+ const primitiveItemType = itemSchema?.type;
1154
+ const isPrimitiveArray =
1155
+ primitiveArrayTypes.has(primitiveItemType) &&
1156
+ !itemSchema?.format;
1157
+
1158
+ const parsePrimitiveValue = (rawValue) => {
1159
+ if (primitiveItemType === "number") {
1160
+ const parsed = Number.parseFloat(rawValue);
1161
+ return Number.isFinite(parsed) ? parsed : rawValue;
1162
+ }
1163
+ if (primitiveItemType === "integer") {
1164
+ const parsed = Number.parseInt(rawValue, 10);
1165
+ return Number.isFinite(parsed) ? parsed : rawValue;
1166
+ }
1167
+ if (primitiveItemType === "boolean") {
1168
+ return rawValue === "true";
1169
+ }
1170
+ return rawValue;
1171
+ };
1153
1172
 
1154
1173
  // Check layout preference: use 'open' for simple string arrays by default, or if explicitly set
1155
1174
  let arrayLayout = ui?.["ui:arrayLayout"];
1156
1175
  if (!arrayLayout) {
1157
1176
  // If not explicitly set, use global option with smart default based on array type
1158
- const globalDefault = this.#getOption("layouts.arrays", "default");
1159
- arrayLayout =
1160
- globalDefault === "default" && isSimpleStringArray
1161
- ? "open"
1162
- : globalDefault;
1177
+ arrayLayout = isPrimitiveArray ? "open" : this.#getOption("layouts.arrays", "default");
1163
1178
  }
1164
1179
 
1165
- const useOpenGroup = arrayLayout === "open" && isSimpleStringArray;
1180
+ const useOpenGroup = arrayLayout === "open" && isPrimitiveArray;
1166
1181
 
1167
1182
  // Check if this is a single-selection array (maxItems: 1) for radio group
1168
1183
  const isSingleSelection = node.schema?.maxItems === 1;
@@ -1189,11 +1204,13 @@ export class SchemaForm extends LitElement {
1189
1204
  this.#setByPath(
1190
1205
  this.#data,
1191
1206
  path,
1192
- checkedInput && checkedInput.value ? [checkedInput.value] : []
1207
+ checkedInput && checkedInput.value
1208
+ ? [parsePrimitiveValue(checkedInput.value)]
1209
+ : []
1193
1210
  );
1194
1211
  } else {
1195
1212
  // For checkbox groups, all items in DOM are in the array
1196
- this.#setByPath(this.#data, path, values);
1213
+ this.#setByPath(this.#data, path, values.map((entry) => parsePrimitiveValue(entry)));
1197
1214
  }
1198
1215
  this.#emit("pw:array-change", {
1199
1216
  path,
@@ -1211,7 +1228,9 @@ export class SchemaForm extends LitElement {
1211
1228
  this.#setByPath(
1212
1229
  this.#data,
1213
1230
  path,
1214
- checkedInput && checkedInput.value ? [checkedInput.value] : []
1231
+ checkedInput && checkedInput.value
1232
+ ? [parsePrimitiveValue(checkedInput.value)]
1233
+ : []
1215
1234
  );
1216
1235
  this.#emit("pw:array-change", {
1217
1236
  path,
@@ -1253,16 +1272,16 @@ export class SchemaForm extends LitElement {
1253
1272
  ${arr.map((value, i) => {
1254
1273
  const id = `${path}-${i}`;
1255
1274
  const isChecked = isSingleSelection
1256
- ? value === selectedValue
1275
+ ? String(value) === String(selectedValue)
1257
1276
  : false;
1258
1277
  return html`
1259
1278
  <label for=${id}>
1260
- <span data-label>${value}</span>
1279
+ <span data-label>${String(value)}</span>
1261
1280
  <input
1262
1281
  id=${id}
1263
1282
  type=${inputType}
1264
1283
  name=${path}
1265
- value=${value}
1284
+ value=${String(value)}
1266
1285
  ?checked=${isChecked}
1267
1286
  />
1268
1287
  </label>
@@ -1408,6 +1427,7 @@ export class SchemaForm extends LitElement {
1408
1427
  schema: node.schema,
1409
1428
  get: (p) => this.#getByPath(this.#data, p ?? path),
1410
1429
  set: (val, p) => this.#assignValue(p ?? path, val),
1430
+ unset: (p) => this.#unsetValue(p ?? path),
1411
1431
  attrs,
1412
1432
  host: this,
1413
1433
  };
@@ -1496,6 +1516,11 @@ export class SchemaForm extends LitElement {
1496
1516
  const isRange = node.widgetKey === "input-range";
1497
1517
  const useRangeOutput =
1498
1518
  isRange && this.#getOption("enhancements.rangeOutput", true);
1519
+
1520
+ // Add data-color for color inputs if enabled
1521
+ const isColorInput = node.widgetKey === "input-color";
1522
+ const useColorInput =
1523
+ isColorInput && this.#getOption("enhancements.colorInput", true);
1499
1524
 
1500
1525
  // Build class list for label
1501
1526
  const labelClasses = [];
@@ -1540,7 +1565,7 @@ export class SchemaForm extends LitElement {
1540
1565
  const after = this.#renderCustomContent(ui?.["ui:after"], renderContext);
1541
1566
 
1542
1567
  const labelTpl = html`
1543
- <label for=${id} ?data-toggle=${isToggle} class=${ifDefined(labelClass)}>
1568
+ <label for=${id} ?data-toggle=${isToggle} ?data-color=${useColorInput} class=${ifDefined(labelClass)}>
1544
1569
  ${renderControlAndLabel(isToggle)}
1545
1570
  ${help ? html`<div data-help>${help}</div>` : nothing}
1546
1571
  </label>
@@ -1675,10 +1700,28 @@ export class SchemaForm extends LitElement {
1675
1700
  // Range input renderer for ui:widget = 'input-range'
1676
1701
  this.defineRenderer(
1677
1702
  "input-range",
1678
- ({ id, path, value, attrs, set, ui }) => {
1703
+ ({ id, path, value, attrs, set, unset, ui, schema }) => {
1679
1704
  const min = ui?.["ui:min"] ?? attrs.min ?? 0;
1680
1705
  const max = ui?.["ui:max"] ?? attrs.max ?? 100;
1681
- const step = attrs.step || 1;
1706
+ const step =
1707
+ ui?.["ui:step"] ??
1708
+ ui?.["ui:options"]?.step ??
1709
+ attrs.step ??
1710
+ (Number(min) >= 0 && Number(max) <= 1 ? 0.01 : 1);
1711
+ const fallbackExample =
1712
+ Array.isArray(schema?.examples) && schema.examples.length > 0
1713
+ ? schema.examples[0]
1714
+ : undefined;
1715
+ const defaultValue = attrs.placeholder ?? fallbackExample;
1716
+ const parsedDefault = Number.parseFloat(defaultValue);
1717
+ const hasNumericDefault = Number.isFinite(parsedDefault);
1718
+ const visualValue =
1719
+ value !== undefined && value !== null
1720
+ ? Number(value)
1721
+ : hasNumericDefault
1722
+ ? Math.min(Number(max), Math.max(Number(min), parsedDefault))
1723
+ : Number(min);
1724
+ const canUnset = Boolean(ui?.["ui:allowUnset"]) && defaultValue !== undefined;
1682
1725
  return html`
1683
1726
  <div class="range-container">
1684
1727
  <input
@@ -1688,12 +1731,29 @@ export class SchemaForm extends LitElement {
1688
1731
  min=${min}
1689
1732
  max=${max}
1690
1733
  step=${step}
1691
- .value=${value ?? min}
1734
+ .value=${visualValue}
1692
1735
  ?disabled=${!!attrs.disabled}
1693
1736
  @input=${(e) => set(Number(e.target.value))}
1694
1737
  />
1695
- <div class="range-bubble" aria-hidden="true">${value ?? min}</div>
1738
+ <div class="range-bubble" aria-hidden="true">${visualValue}</div>
1696
1739
  </div>
1740
+ ${canUnset
1741
+ ? html`
1742
+ <div class="flex items-center justify-between gap-sm">
1743
+ <small class="text-muted">Default: ${defaultValue}</small>
1744
+ <a
1745
+ href="#"
1746
+ class="text-muted"
1747
+ @click=${(event) => {
1748
+ event.preventDefault();
1749
+ unset(path);
1750
+ }}
1751
+ >
1752
+ Use default
1753
+ </a>
1754
+ </div>
1755
+ `
1756
+ : nothing}
1697
1757
  `;
1698
1758
  }
1699
1759
  );
@@ -1797,19 +1857,38 @@ export class SchemaForm extends LitElement {
1797
1857
 
1798
1858
  this.defineRenderer(
1799
1859
  "input-color",
1800
- ({ id, path, value, attrs, set }) => html`
1860
+ ({ id, path, value, attrs, set, schema }) => {
1861
+ const fallbackExample =
1862
+ Array.isArray(schema?.examples) && schema.examples.length > 0
1863
+ ? schema.examples[0]
1864
+ : undefined;
1865
+ const hasUserValue =
1866
+ value !== undefined && value !== null && String(value).trim() !== "";
1867
+ const hasFallbackExample =
1868
+ fallbackExample !== undefined &&
1869
+ fallbackExample !== null &&
1870
+ String(fallbackExample).trim() !== "";
1871
+ const isUnset = !hasUserValue && !hasFallbackExample;
1872
+ const controlValue = hasUserValue
1873
+ ? value
1874
+ : hasFallbackExample
1875
+ ? fallbackExample
1876
+ : "#000000";
1877
+ return html`
1801
1878
  <input
1802
1879
  id=${id}
1803
1880
  name=${path}
1881
+ data-color-unset=${isUnset ? "1" : "0"}
1804
1882
  placeholder=${ifDefined(attrs.placeholder)}
1805
1883
  type="color"
1806
- .value=${value ?? ""}
1884
+ .value=${controlValue}
1807
1885
  ?readonly=${!!attrs.readOnly}
1808
1886
  ?disabled=${!!attrs.disabled}
1809
1887
  ?required=${!!attrs.required}
1810
1888
  @input=${(e) => set(e.target.value)}
1811
1889
  />
1812
- `
1890
+ `;
1891
+ }
1813
1892
  );
1814
1893
 
1815
1894
  this.defineRenderer(
@@ -2272,6 +2351,24 @@ export class SchemaForm extends LitElement {
2272
2351
  this.#emit("pw:value-change", { path, name: path, value: val, validity });
2273
2352
  }
2274
2353
 
2354
+ #unsetValue(path) {
2355
+ this.#deleteByPathPrefix(this.#data, path);
2356
+
2357
+ const hadDependents = this.#applyCalculatedValues(path);
2358
+ if (!hadDependents) {
2359
+ this.requestUpdate();
2360
+ }
2361
+
2362
+ const validity = { valid: true };
2363
+ this.#emit("pw:value-change", {
2364
+ path,
2365
+ name: path,
2366
+ value: undefined,
2367
+ validity,
2368
+ unset: true,
2369
+ });
2370
+ }
2371
+
2275
2372
  #applyCalculatedValues(changedPath) {
2276
2373
  // Find fields that depend on the changed path
2277
2374
  const dependents = this.#dependencies.get(changedPath);