@pure-ds/core 0.4.22 → 0.4.24

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.
@@ -304,7 +304,7 @@ class PdsDrawer extends HTMLElement {
304
304
  width: 100%; max-width: 100%;
305
305
  margin: 0;
306
306
  border-radius: var(--drawer-radius, var(--radius-lg));
307
- overflow: clip; contain: layout paint style; will-change: transform;
307
+ overflow: visible; contain: layout style; will-change: transform;
308
308
  touch-action: none;
309
309
  outline: none;
310
310
  }
@@ -11,7 +11,7 @@ function getStep(value) {
11
11
  // Default options for pds-form
12
12
  const DEFAULT_OPTIONS = {
13
13
  widgets: {
14
- booleans: "toggle", // 'toggle' | 'checkbox'
14
+ booleans: "toggle", // 'toggle' | 'toggle-with-icons' | 'checkbox'
15
15
  numbers: "input", // 'input' | 'range'
16
16
  selects: "standard", // 'standard' | 'dropdown'
17
17
  },
@@ -669,10 +669,9 @@ export class SchemaForm extends LitElement {
669
669
  return useRange ? "input-range" : "input-number";
670
670
  }
671
671
  if (schema.type === "boolean") {
672
- // Check if toggle should be used
673
- const useToggle =
674
- this.#getOption("widgets.booleans", "toggle") === "toggle";
675
- return useToggle ? "toggle" : "checkbox";
672
+ // Return the actual boolean widget type
673
+ const booleanWidget = this.#getOption("widgets.booleans", "toggle");
674
+ return booleanWidget === "checkbox" ? "checkbox" : booleanWidget;
676
675
  }
677
676
  return "input-text";
678
677
  }
@@ -1489,14 +1488,20 @@ export class SchemaForm extends LitElement {
1489
1488
  this.#emit("pw:after-render-field", { path, schema: node.schema })
1490
1489
  );
1491
1490
 
1492
- // Add data-toggle for toggle switches
1493
- const isToggle = node.widgetKey === "toggle";
1491
+ // Add data-toggle for toggle switches (both toggle and toggle-with-icons)
1492
+ const isToggle = node.widgetKey === "toggle" || node.widgetKey === "toggle-with-icons";
1493
+ const useIconToggle = node.widgetKey === "toggle-with-icons";
1494
1494
 
1495
1495
  // Add range-output class for range inputs if enabled
1496
1496
  const isRange = node.widgetKey === "input-range";
1497
1497
  const useRangeOutput =
1498
1498
  isRange && this.#getOption("enhancements.rangeOutput", true);
1499
- const labelClass = useRangeOutput ? "range-output" : undefined;
1499
+
1500
+ // Build class list for label
1501
+ const labelClasses = [];
1502
+ if (useRangeOutput) labelClasses.push("range-output");
1503
+ if (useIconToggle) labelClasses.push("with-icons");
1504
+ const labelClass = labelClasses.length > 0 ? labelClasses.join(" ") : undefined;
1500
1505
 
1501
1506
  const renderControlAndLabel = (isToggle) => {
1502
1507
  if (isToggle) return html`${controlTpl} <span data-label>${label}</span>`;
@@ -1855,6 +1860,22 @@ export class SchemaForm extends LitElement {
1855
1860
  `
1856
1861
  );
1857
1862
 
1863
+ // Toggle switch with icons (same as toggle, styling comes from .with-icons class on label)
1864
+ this.defineRenderer(
1865
+ "toggle-with-icons",
1866
+ ({ id, path, value, attrs, set }) => html`
1867
+ <input
1868
+ id=${id}
1869
+ name=${path}
1870
+ type="checkbox"
1871
+ .checked=${!!value}
1872
+ ?disabled=${!!attrs.disabled}
1873
+ ?required=${!!attrs.required}
1874
+ @change=${(e) => set(!!e.target.checked)}
1875
+ />
1876
+ `
1877
+ );
1878
+
1858
1879
  this.defineRenderer(
1859
1880
  "select",
1860
1881
  ({ id, path, value, attrs, set, schema, ui, host }) => {
package/readme.md CHANGED
@@ -246,10 +246,18 @@ Auto-defined when used. Lazy-loaded via dynamic imports. Styled by your tokens.
246
246
  npm install @pure-ds/core
247
247
  ```
248
248
 
249
- Assets (components, icons) are auto-copied to your project during install. To manually sync:
249
+ **Post-install automation:**
250
+
251
+ During installation, PDS automatically:
252
+ - Creates a default `pds.config.js` (if one doesn't exist)
253
+ - Copies Copilot/AI instructions to `.github/copilot-instructions.md`
254
+ - Adds `pds:export` and `pds:build-icons` scripts to your `package.json`
255
+ - Runs `pds:export` to generate static assets
256
+
257
+ To manually re-sync assets:
250
258
 
251
259
  ```bash
252
- node node_modules/@pure-ds/core/packages/pds-cli/bin/postinstall.js
260
+ npm run pds:export
253
261
  ```
254
262
 
255
263
  ### Lit Import Convention
@@ -1560,6 +1568,27 @@ await PDS.start({ design: myPreset });
1560
1568
  | `npm run pds:css-data` | Generate CSS IntelliSense (tokens, classes, attributes) |
1561
1569
  | `npm run pds:build-icons` | Build custom icon sprite |
1562
1570
  | `npm run sync-assets` | Sync assets between locations |
1571
+ | `npx pds-init-config` | Create default `pds.config.js` with helpful examples |
1572
+
1573
+ ### Initialize Configuration
1574
+
1575
+ Create a starter `pds.config.js` file with commented examples:
1576
+
1577
+ ```bash
1578
+ # Create config in current directory
1579
+ npx pds-init-config
1580
+
1581
+ # Force overwrite existing config
1582
+ npx pds-init-config --force
1583
+ ```
1584
+
1585
+ This generates a `pds.config.js` with:
1586
+ - Basic `mode` and `preset` settings
1587
+ - Commented examples for design token overrides
1588
+ - Template for custom progressive enhancers
1589
+ - Template for lazy-loaded component configuration
1590
+
1591
+ **Note:** During `npm install`, PDS automatically creates this file if it doesn't exist.
1563
1592
 
1564
1593
  ### Export Static Assets
1565
1594
 
@@ -1859,10 +1888,61 @@ export default {
1859
1888
  ### Components Not Loading
1860
1889
 
1861
1890
  1. Verify components directory exists
1862
- 2. Check import map for `#pds/lit`
1891
+ 2. Check import map for `#pds/lit` (required for Lit components - see below)
1863
1892
  3. Manually sync: `node node_modules/pure-ds/packages/pds-cli/bin/postinstall.js`
1864
1893
  4. Check browser console for errors
1865
1894
 
1895
+ ### Lit Components Not Working
1896
+
1897
+ **Symptoms:** `<pds-form>` or other Lit-based components fail to load with module resolution errors.
1898
+
1899
+ **Components requiring Lit:**
1900
+ - `<pds-form>` - JSON Schema forms
1901
+ - `<pds-drawer>` - Drawer/sidebar panels
1902
+
1903
+ **Solution:** Add import map to your HTML `<head>`:
1904
+
1905
+ ```html
1906
+ <script type="importmap">
1907
+ {
1908
+ "imports": {
1909
+ "#pds/lit": "/assets/js/lit.js"
1910
+ }
1911
+ }
1912
+ </script>
1913
+ ```
1914
+
1915
+ Or in bundlers (Vite, Webpack, etc.):
1916
+
1917
+ ```javascript
1918
+ // vite.config.js
1919
+ export default {
1920
+ resolve: {
1921
+ alias: { '#pds/lit': 'lit' }
1922
+ }
1923
+ };
1924
+
1925
+ // webpack.config.js
1926
+ module.exports = {
1927
+ resolve: {
1928
+ alias: { '#pds/lit': 'lit' }
1929
+ }
1930
+ };
1931
+ ```
1932
+
1933
+ **Note:** Wait for components to load before accessing their APIs:
1934
+
1935
+ ```javascript
1936
+ // ❌ Don't do this
1937
+ const form = document.querySelector('pds-form');
1938
+ form.getFormData(); // May fail if component not loaded yet
1939
+
1940
+ // ✅ Do this instead
1941
+ await customElements.whenDefined('pds-form');
1942
+ const form = document.querySelector('pds-form');
1943
+ form.getFormData(); // Safe
1944
+ ```
1945
+
1866
1946
  ### Flash of Unstyled Content
1867
1947
 
1868
1948
  ```javascript
@@ -737,7 +737,6 @@ export const presets = {
737
737
  "Data-dense business intelligence app interface with organized hierarchy and professional polish",
738
738
  options: {
739
739
  liquidGlassEffects: false,
740
- backgroundMesh: 2,
741
740
  },
742
741
  colors: {
743
742
  primary: "#0066cc", // corporate blue for primary actions
@@ -815,7 +814,7 @@ presets.default = {
815
814
  form: {
816
815
  options: {
817
816
  widgets: {
818
- booleans: "toggle", // 'toggle' | 'checkbox'
817
+ booleans: "toggle", // 'toggle' | 'toggle-with-icons' | 'checkbox'
819
818
  numbers: "input", // 'input' | 'range'
820
819
  selects: "standard", // 'standard' | 'dropdown'
821
820
  },
@@ -1923,6 +1923,12 @@ label {
1923
1923
  line-height: var(--font-line-height-relaxed);
1924
1924
  }
1925
1925
 
1926
+ input, textarea, select {
1927
+ &:focus {
1928
+ outline: none;
1929
+ }
1930
+ }
1931
+
1926
1932
  input, textarea, select {
1927
1933
  width: 100%;
1928
1934
  min-height: ${minInputHeight}px;
@@ -1940,11 +1946,7 @@ input, textarea, select {
1940
1946
  -webkit-appearance: none;
1941
1947
 
1942
1948
  &:focus {
1943
- outline: none;
1944
1949
  border-color: var(--color-primary-500);
1945
- box-shadow: 0 0 0 ${focusWidth}px color-mix(in oklab, var(--color-primary-500) ${Math.round(
1946
- (focusRingOpacity || 0.3) * 100
1947
- )}%, transparent);
1948
1950
  background-color: var(--color-surface-base);
1949
1951
  }
1950
1952
 
@@ -2324,6 +2326,25 @@ label[data-toggle] {
2324
2326
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
2325
2327
  }
2326
2328
 
2329
+ /* Icons in toggle knob (opt-in via .with-icons class) */
2330
+ &.with-icons .toggle-knob::before {
2331
+ content: "✕";
2332
+ position: absolute;
2333
+ inset: 0;
2334
+ display: flex;
2335
+ align-items: center;
2336
+ justify-content: center;
2337
+ font-size: 12px;
2338
+ font-weight: bold;
2339
+ color: var(--color-gray-600);
2340
+ transition: opacity 200ms ease;
2341
+ }
2342
+
2343
+ &.with-icons:has(input[type="checkbox"]:checked) .toggle-knob::before {
2344
+ content: "✓";
2345
+ color: var(--color-primary-600);
2346
+ }
2347
+
2327
2348
  /* Toggle switch when checked - using :has() selector */
2328
2349
  &:has(input[type="checkbox"]:checked) .toggle-switch {
2329
2350
  background-color: var(--color-primary-fill);
@@ -2887,15 +2908,28 @@ tbody {
2887
2908
  cursor: pointer;
2888
2909
  padding: var(--spacing-3) var(--spacing-4);
2889
2910
  list-style: none;
2890
- outline: none;
2891
2911
  display: flex;
2892
2912
  align-items: center;
2893
2913
  gap: var(--spacing-2);
2914
+ border-radius: var(--radius-sm);
2915
+ transition: background-color var(--transition-fast), box-shadow var(--transition-fast);
2894
2916
 
2895
2917
  &::-webkit-details-marker {
2896
2918
  display: none;
2897
2919
  }
2898
2920
 
2921
+ &:hover {
2922
+ background-color: var(--color-surface-subtle);
2923
+ }
2924
+
2925
+ &:focus {
2926
+ outline: none;
2927
+ }
2928
+
2929
+ &:focus-visible {
2930
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-primary-500) 30%, transparent);
2931
+ }
2932
+
2899
2933
  /* Chevron indicator */
2900
2934
  &::after {
2901
2935
  content: "";
@@ -3628,6 +3662,13 @@ nav[data-dropdown] {
3628
3662
  white-space: nowrap;
3629
3663
  }
3630
3664
 
3665
+ /* Required Legend Utility */
3666
+ :where(.required-legend) {
3667
+ display: block;
3668
+ margin: var(--spacing-3) 0;
3669
+ color: var(--color-text-muted);
3670
+ }
3671
+
3631
3672
  /* Max-width utilities */
3632
3673
  .max-w-sm { max-width: 400px; } .max-w-md { max-width: 600px; } .max-w-lg { max-width: 800px; } .max-w-xl { max-width: 1200px; }
3633
3674
 
package/src/js/pds.js CHANGED
@@ -961,10 +961,27 @@ async function __setupAutoDefinerAndEnhancers(options) {
961
961
  enhancers: mergedEnhancers,
962
962
  onError: (tag, err) => {
963
963
  if (typeof tag === "string" && tag.startsWith("pds-")) {
964
- // No config available in this context, using console
965
- console.warn(
966
- `⚠️ PDS component <${tag}> not found. Assets may not be installed.`
967
- );
964
+ // Check if this is a Lit-dependent component with missing #pds/lit import map
965
+ const litDependentComponents = ['pds-form', 'pds-drawer'];
966
+ const isLitComponent = litDependentComponents.includes(tag);
967
+ const isMissingLitError = err?.message?.includes('#pds/lit') ||
968
+ err?.message?.includes('Failed to resolve module specifier');
969
+
970
+ if (isLitComponent && isMissingLitError) {
971
+ console.error(
972
+ `❌ PDS component <${tag}> requires Lit but #pds/lit is not in import map.\n` +
973
+ `Add this to your HTML <head>:\n` +
974
+ `<script type="importmap">\n` +
975
+ ` { "imports": { "#pds/lit": "./path/to/lit.js" } }\n` +
976
+ `</script>\n` +
977
+ `See: https://github.com/pure-ds/core#lit-components`
978
+ );
979
+ } else {
980
+ // Generic component not found warning
981
+ console.warn(
982
+ `⚠️ PDS component <${tag}> not found. Assets may not be installed.`
983
+ );
984
+ }
968
985
  } else {
969
986
  console.error(`❌ Auto-define error for <${tag}>:`, err);
970
987
  }