@nysds/components 1.18.3 → 1.19.1-alpha-1

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 (106) hide show
  1. package/custom-elements.json +582 -191
  2. package/dist/.vscode/vscode.html-custom-data.json +16 -5
  3. package/dist/custom-elements.json +582 -191
  4. package/dist/icons/ac_unit.svg +8 -0
  5. package/dist/icons/account_balance_filled.svg +8 -0
  6. package/dist/icons/account_circle.svg +8 -0
  7. package/dist/icons/add.svg +8 -0
  8. package/dist/icons/air.svg +8 -0
  9. package/dist/icons/arrow_back.svg +8 -0
  10. package/dist/icons/arrow_downward.svg +8 -0
  11. package/dist/icons/arrow_forward.svg +8 -0
  12. package/dist/icons/arrow_upward.svg +8 -0
  13. package/dist/icons/attach_file.svg +8 -0
  14. package/dist/icons/calendar_month.svg +8 -0
  15. package/dist/icons/cancel.svg +8 -0
  16. package/dist/icons/cancel_filled.svg +8 -0
  17. package/dist/icons/check.svg +8 -0
  18. package/dist/icons/check_circle.svg +8 -0
  19. package/dist/icons/chevron_down.svg +8 -0
  20. package/dist/icons/chevron_left.svg +8 -0
  21. package/dist/icons/chevron_right.svg +8 -0
  22. package/dist/icons/chevron_up.svg +8 -0
  23. package/dist/icons/clear_day.svg +8 -0
  24. package/dist/icons/close.svg +8 -0
  25. package/dist/icons/code.svg +8 -0
  26. package/dist/icons/content_copy.svg +8 -0
  27. package/dist/icons/coronavirus.svg +8 -0
  28. package/dist/icons/delete.svg +8 -0
  29. package/dist/icons/download.svg +8 -0
  30. package/dist/icons/download_done.svg +8 -0
  31. package/dist/icons/drive_folder_upload.svg +8 -0
  32. package/dist/icons/edit_square.svg +8 -0
  33. package/dist/icons/emergency_home.svg +8 -0
  34. package/dist/icons/error.svg +8 -0
  35. package/dist/icons/expand_all.svg +8 -0
  36. package/dist/icons/filter_alt.svg +8 -0
  37. package/dist/icons/filter_list.svg +8 -0
  38. package/dist/icons/height.svg +8 -0
  39. package/dist/icons/help.svg +8 -0
  40. package/dist/icons/info.svg +8 -0
  41. package/dist/icons/language.svg +8 -0
  42. package/dist/icons/language_filled.svg +8 -0
  43. package/dist/icons/link.svg +8 -0
  44. package/dist/icons/lock_filled.svg +8 -0
  45. package/dist/icons/mail.svg +8 -0
  46. package/dist/icons/manifest.json +84 -0
  47. package/dist/icons/menu.svg +8 -0
  48. package/dist/icons/more_vert.svg +8 -0
  49. package/dist/icons/notifications.svg +8 -0
  50. package/dist/icons/open_in_new.svg +8 -0
  51. package/dist/icons/phone_in_talk.svg +8 -0
  52. package/dist/icons/print.svg +8 -0
  53. package/dist/icons/progress_activity.svg +8 -0
  54. package/dist/icons/publish.svg +8 -0
  55. package/dist/icons/rainy.svg +8 -0
  56. package/dist/icons/refresh.svg +8 -0
  57. package/dist/icons/remove.svg +8 -0
  58. package/dist/icons/search.svg +8 -0
  59. package/dist/icons/share.svg +8 -0
  60. package/dist/icons/sms.svg +8 -0
  61. package/dist/icons/social_bluesky.svg +8 -0
  62. package/dist/icons/social_facebook.svg +8 -0
  63. package/dist/icons/social_flickr.svg +8 -0
  64. package/dist/icons/social_google_play.svg +8 -0
  65. package/dist/icons/social_instagram.svg +10 -0
  66. package/dist/icons/social_linkedin.svg +8 -0
  67. package/dist/icons/social_pinterest.svg +8 -0
  68. package/dist/icons/social_rss.svg +10 -0
  69. package/dist/icons/social_snapchat.svg +8 -0
  70. package/dist/icons/social_soundcloud.svg +21 -0
  71. package/dist/icons/social_threads.svg +9 -0
  72. package/dist/icons/social_tiktok.svg +8 -0
  73. package/dist/icons/social_tumblr.svg +8 -0
  74. package/dist/icons/social_vimeo.svg +8 -0
  75. package/dist/icons/social_x.svg +8 -0
  76. package/dist/icons/social_youtube.svg +8 -0
  77. package/dist/icons/sort.svg +8 -0
  78. package/dist/icons/straight.svg +8 -0
  79. package/dist/icons/thumb_down.svg +8 -0
  80. package/dist/icons/thumb_up.svg +8 -0
  81. package/dist/icons/upload_file.svg +8 -0
  82. package/dist/icons/visibility.svg +8 -0
  83. package/dist/icons/visibility_off.svg +8 -0
  84. package/dist/icons/warning.svg +8 -0
  85. package/dist/nysds.es.js +3672 -3585
  86. package/dist/nysds.es.js.map +1 -1
  87. package/dist/nysds.js +316 -866
  88. package/dist/nysds.js.map +1 -1
  89. package/dist/packages/nys-button/src/nys-button.d.ts +4 -0
  90. package/dist/packages/nys-divider/src/nys-divider.d.ts +2 -0
  91. package/dist/packages/nys-icon/src/icon-cache.d.ts +11 -0
  92. package/dist/packages/nys-icon/src/icon-library-registry.d.ts +47 -0
  93. package/dist/packages/nys-icon/src/index.d.ts +3 -0
  94. package/dist/packages/nys-icon/src/nys-icon.d.ts +40 -11
  95. package/dist/packages/nys-radiobutton/src/nys-radiobutton.d.ts +1 -38
  96. package/dist/packages/nys-radiobutton/src/nys-radiogroup.d.ts +17 -7
  97. package/package.json +12 -8
  98. package/packages/react/NysDivider.d.ts +3 -0
  99. package/packages/react/NysDivider.js +2 -1
  100. package/packages/react/NysIcon.d.ts +11 -2
  101. package/packages/react/NysIcon.js +26 -3
  102. package/packages/react/NysRadiobutton.d.ts +7 -23
  103. package/packages/react/NysRadiobutton.js +1 -3
  104. package/packages/react/NysRadiogroup.d.ts +18 -2
  105. package/packages/react/NysRadiogroup.js +17 -1
  106. package/packages/react/nysds-jsx.d.ts +30 -20
@@ -160,6 +160,8 @@ export declare class NysButton extends LitElement {
160
160
  */
161
161
  target: "_self" | "_blank" | "_parent" | "_top" | "framename";
162
162
  private _internals;
163
+ private _hasPrefixSlot;
164
+ private _hasSuffixSlot;
163
165
  /**
164
166
  * Lifecycle methods
165
167
  * --------------------------------------------------------------------------
@@ -172,6 +174,8 @@ export declare class NysButton extends LitElement {
172
174
  * --------------------------------------------------------------------------
173
175
  */
174
176
  private _generateUniqueId;
177
+ private _onPrefixSlotChange;
178
+ private _onSuffixSlotChange;
175
179
  private _manageFormAction;
176
180
  /**
177
181
  * Event Handlers
@@ -18,6 +18,8 @@ export declare class NysDivider extends LitElement {
18
18
  static styles: import("lit").CSSResult;
19
19
  /** Adjusts colors for dark backgrounds. */
20
20
  inverted: boolean;
21
+ /** If true, the divider will use a lighter color. */
22
+ subtle: boolean;
21
23
  constructor();
22
24
  connectedCallback(): void;
23
25
  /**
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Icon Cache
3
+ *
4
+ * Shared SVG fetch and parse cache. Deduplicates concurrent requests
5
+ * for the same icon URL. Each consumer gets a cloned SVGElement via
6
+ * `cloneNode(true)` so DOM nodes are never shared.
7
+ */
8
+ /** Fetch and parse an SVG from a URL. Returns a cloned SVGElement (safe for multiple consumers). */
9
+ export declare function fetchIcon(url: string): Promise<SVGElement>;
10
+ /** Clear one or all entries from the cache. */
11
+ export declare function clearIconCache(url?: string): void;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Icon Library Registry
3
+ *
4
+ * Global registry for icon libraries. The "default" library resolves
5
+ * NYSDS icons from colocated SVG files extracted at build time.
6
+ * Custom libraries (Font Awesome, Material Icons, etc.) can be
7
+ * registered at runtime via `registerIconLibrary()`.
8
+ *
9
+ * The registry and watcher maps are stored on `window` so that even
10
+ * when bundlers (Storybook Vite, etc.) create duplicate module
11
+ * instances, every copy shares a single source of truth.
12
+ */
13
+ export interface IconLibrary {
14
+ /** Given an icon name, return the URL to its SVG file. Return undefined if not found. */
15
+ resolver: (name: string) => string | undefined;
16
+ /** Optional post-fetch transform applied to the parsed SVGElement. */
17
+ mutator?: (svg: SVGElement) => void;
18
+ }
19
+ export interface NysIconWatcher {
20
+ redraw(): void;
21
+ }
22
+ interface NysIconGlobals {
23
+ __nysIconRegistry: Map<string, IconLibrary>;
24
+ __nysIconWatchers: Map<string, Set<NysIconWatcher>>;
25
+ }
26
+ declare global {
27
+ interface Window extends NysIconGlobals {
28
+ }
29
+ }
30
+ /** Register or replace a named icon library. All watching icons using this library will redraw.
31
+ * @example Register a Font Awesome library with a custom resolver:
32
+ * ```ts
33
+ * registerIconLibrary("fa", {
34
+ * resolver: (name) => `https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/svg/${name}.svg`
35
+ * });
36
+ * ```
37
+ */
38
+ export declare function registerIconLibrary(name: string, library: IconLibrary): void;
39
+ /** Remove a registered icon library. All watching icons using this library will redraw. */
40
+ export declare function unregisterIconLibrary(name: string): void;
41
+ /** Get a registered icon library by name. */
42
+ export declare function getIconLibrary(name: string): IconLibrary | undefined;
43
+ /** Subscribe an icon instance to library change notifications. */
44
+ export declare function watchIconLibrary(name: string, watcher: NysIconWatcher): void;
45
+ /** Unsubscribe an icon instance from library change notifications. */
46
+ export declare function unwatchIconLibrary(name: string, watcher: NysIconWatcher): void;
47
+ export {};
@@ -1 +1,4 @@
1
1
  export * from "./nys-icon";
2
+ export { registerIconLibrary, unregisterIconLibrary, } from "./icon-library-registry";
3
+ export type { IconLibrary } from "./icon-library-registry";
4
+ export { clearIconCache } from "./icon-cache";
@@ -1,27 +1,39 @@
1
1
  import { LitElement } from "lit";
2
+ import { NysIconWatcher } from "./icon-library-registry";
2
3
  /**
3
- * Renders SVG icons from the NYSDS icon library (Material Symbols). Decorative by default (`aria-hidden`).
4
+ * Renders SVG icons from a registered icon library. The built-in NYSDS icon
5
+ * library (Material Symbols) is the default. Custom libraries (Font Awesome,
6
+ * Material Icons, etc.) can be registered via `registerIconLibrary()`.
4
7
  *
5
- * Pass `name` to select an icon from the library. Use `ariaLabel` to make the icon accessible
6
- * (removes `aria-hidden`). Supports size presets, rotation, flipping, and custom colors.
8
+ * Pass `name` to select an icon. Use `library` to choose a registered library
9
+ * (defaults to `"default"` for NYSDS icons). Use `ariaLabel` to make the icon
10
+ * accessible (removes `aria-hidden`). Supports size presets, rotation,
11
+ * flipping, and custom colors.
7
12
  *
8
- * @summary SVG icon from Material Symbols library with size, rotation, and color options.
13
+ * @summary SVG icon with swappable library support, size, rotation, and color options.
9
14
  * @element nys-icon
10
15
  *
11
- * @example Basic icon
16
+ * @example Basic icon (default NYSDS library)
12
17
  * ```html
13
18
  * <nys-icon name="check_circle" size="lg"></nys-icon>
14
19
  * ```
15
20
  *
21
+ * @example Font Awesome icon
22
+ * ```html
23
+ * <nys-icon name="house" library="fa" size="lg"></nys-icon>
24
+ * ```
25
+ *
16
26
  * @example Accessible icon with label
17
27
  * ```html
18
28
  * <nys-icon name="warning" ariaLabel="Warning" color="var(--nys-color-warning)"></nys-icon>
19
29
  * ```
20
30
  */
21
- export declare class NysIcon extends LitElement {
31
+ export declare class NysIcon extends LitElement implements NysIconWatcher {
22
32
  static styles: import("lit").CSSResult;
23
- /** Icon name from Material Symbols library. Required. */
33
+ /** Icon name to resolve from the selected library. Required. */
24
34
  name: string;
35
+ /** Which registered icon library to use. Defaults to the built-in NYSDS library. */
36
+ library: string;
25
37
  /** Accessible label. When set, removes `aria-hidden` and adds `aria-label` to the SVG. */
26
38
  ariaLabel: string;
27
39
  /** Rotation in degrees. Applied via CSS `rotate`. */
@@ -35,11 +47,28 @@ export declare class NysIcon extends LitElement {
35
47
  * @default "md"
36
48
  */
37
49
  size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "12" | "14" | "16" | "18" | "20" | "24" | "32" | "40" | "50";
50
+ private _svg;
51
+ /** Monotonically increasing token so stale async fetches are discarded. */
52
+ private _loadSeq;
53
+ /** Promise for the in-flight icon load. */
54
+ private _loadPromise;
55
+ /** Resolves when the current icon load (if any) is complete. */
56
+ get updateComplete(): Promise<boolean>;
57
+ connectedCallback(): void;
58
+ disconnectedCallback(): void;
59
+ /** Called by the icon library registry when the current library changes. */
60
+ redraw(): void;
38
61
  /**
39
- * Retrieves the SVG element for the given icon name and applies
40
- * accessibility, rotation, flip, color, and size classes.
41
- * @returns SVGElement | null
62
+ * Lit calls firstUpdated after the first render, once all reactive
63
+ * properties (including those set from the template) are resolved.
64
+ * This guarantees the initial _loadIcon runs with the correct name
65
+ * and library values, avoiding the race where updated() might not
66
+ * fire for properties that equal their defaults.
42
67
  */
43
- private getIcon;
68
+ firstUpdated(): void;
69
+ private static _validName;
70
+ updated(changedProps: Map<string, unknown>): void;
71
+ private _loadIcon;
72
+ private _applyAttributes;
44
73
  render(): import("lit-html").TemplateResult<1> | null;
45
74
  }
@@ -1,12 +1,11 @@
1
1
  import { LitElement } from "lit";
2
- import "./nys-radiogroup";
3
2
  /**
4
3
  * A radio button for single selection within a `nys-radiogroup`. Only one radio with the same `name` can be selected.
5
4
  *
6
5
  * Use within `nys-radiogroup` for 2-6 mutually exclusive options. For 7+ options, use `nys-select`.
7
6
  * For multiple selections, use `nys-checkbox`.
8
7
  *
9
- * @summary Radio button for single selection from mutually exclusive options.
8
+ * @summary Radio button for single selection from mutually exclusive options. This is a READONLY data component.
10
9
  * @element nys-radiobutton
11
10
  *
12
11
  * @slot description - Custom HTML description content.
@@ -26,14 +25,6 @@ import "./nys-radiogroup";
26
25
  */
27
26
  export declare class NysRadiobutton extends LitElement {
28
27
  static styles: import("lit").CSSResult;
29
- static shadowRootOptions: {
30
- delegatesFocus: boolean;
31
- clonable?: boolean;
32
- customElementRegistry?: CustomElementRegistry;
33
- mode: ShadowRootMode;
34
- serializable?: boolean;
35
- slotAssignment?: SlotAssignmentMode;
36
- };
37
28
  /** Whether this radio is selected. Only one per group can be checked. */
38
29
  checked: boolean;
39
30
  /** Prevents interaction. */
@@ -61,38 +52,10 @@ export declare class NysRadiobutton extends LitElement {
61
52
  tile: boolean;
62
53
  other: boolean;
63
54
  showOtherError: boolean;
64
- private isMobile;
65
- private _hasUserInteracted;
66
- static buttonGroup: Record<string, NysRadiobutton>;
67
55
  /**
68
56
  * Lifecycle methods
69
57
  * --------------------------------------------------------------------------
70
58
  */
71
59
  connectedCallback(): void;
72
- disconnectedCallback(): void;
73
- updated(changedProperties: Map<string | number | symbol, unknown>): void;
74
- /**
75
- * Functions
76
- * --------------------------------------------------------------------------
77
- */
78
- getInputElement(): Promise<HTMLInputElement | null>;
79
- formResetUpdate(): void;
80
- private _handleResize;
81
- private _clearOtherState;
82
- private _dispatchClearErrorEvent;
83
- /**
84
- * Event Handlers
85
- * --------------------------------------------------------------------------
86
- */
87
- private _emitChangeEvent;
88
- private _emitOtherInputEvent;
89
- private _handleChange;
90
- private _handleFocus;
91
- private _handleBlur;
92
- private _callInputHandling;
93
- private _handleTextInput;
94
- private _handleTextInputBlur;
95
- private _validateOtherAndEmitError;
96
- private _handleOtherKeydown;
97
60
  render(): import("lit-html").TemplateResult<1>;
98
61
  }
@@ -58,8 +58,14 @@ export declare class NysRadiogroup extends LitElement {
58
58
  * @default "md"
59
59
  */
60
60
  size: "sm" | "md";
61
+ _showOtherError: boolean;
61
62
  private selectedValue;
62
63
  private _slottedDescriptionText;
64
+ private _radios;
65
+ private _mobileQuery;
66
+ private isMobile;
67
+ private _hasUserInteracted;
68
+ private _childObserver?;
63
69
  private _internals;
64
70
  /**
65
71
  * Lifecycle methods
@@ -88,20 +94,24 @@ export declare class NysRadiogroup extends LitElement {
88
94
  * Functions
89
95
  * --------------------------------------------------------------------------
90
96
  */
97
+ private _handleMobileQuery;
98
+ private _handleSlotChange;
91
99
  private _initializeChildAttributes;
92
100
  private _updateRadioButtonsSize;
93
- private _updateRadioButtonsTile;
94
- private _updateRadioButtonsShowError;
95
- private _updateRadioButtonsForm;
101
+ private _selectRadio;
96
102
  private _getSlotDescriptionForAria;
97
103
  /**
98
104
  * Event Handlers
99
105
  * --------------------------------------------------------------------------
100
106
  */
101
- private _handleRadioButtonChange;
102
107
  private _handleInvalid;
103
- private _handleChildError;
104
- private _handleChildErrorClear;
105
- private _handleOtherInput;
108
+ private _handleTextInput;
109
+ private _handleTextInputBlur;
110
+ private _validateOtherAndEmitError;
111
+ private _handleOtherKeydown;
112
+ private _handleGroupFocusout;
113
+ private _handleRadiobtnClick;
114
+ private _handleRadiobtnFocus;
115
+ private _handleRadiobtnBlur;
106
116
  render(): import("lit-html").TemplateResult<1>;
107
117
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/components",
3
- "version": "1.18.3",
3
+ "version": "1.19.1-alpha-1",
4
4
  "description": "New York State's design system and code component library.",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -37,17 +37,18 @@
37
37
  "build:all": "npm run clean:dist && npm run lint && npm run lit-analyze || true && cross-env NODE_ENV=production npm run build:packages && npm run build:root && npm run cem && npm run build:mcp",
38
38
  "build:mcp": "npm run build -w @nysds/mcp-server",
39
39
  "build:link": "npm run build:all && npm link && cd packages/styles && npm link",
40
- "lint": "eslint --cache --cache-location node_modules/.cache/eslint && stylelint **/*.scss || true",
41
- "lint:fix": "eslint --fix && stylelint **/*.scss --fix",
40
+ "lint": "eslint --cache --cache-strategy=content --cache-location node_modules/.cache/eslint && (stylelint \"**/*.scss\" || true)",
41
+ "lint:fix": "bash src/scripts/lint-fix.sh",
42
42
  "lit-analyze": "find ./packages/nys-*/ -name '*.ts' ! -name '*.figma.*' | xargs lit-analyzer {}",
43
+ "playwright:install": "npx playwright install --with-deps",
43
44
  "release": "cross-env NODE_ENV=production npm run build:all && cross-env NODE_ENV=production npm run test && npm run cem && cross-env NODE_ENV=production npm publish --workspaces --access public && cross-env NODE_ENV=production npm publish --access public",
44
45
  "release:dry-run": "cross-env NODE_ENV=production npm run build:all && cross-env NODE_ENV=production npm run test && npm run cem && node src/scripts/publish-dry-run.js",
45
46
  "release:alpha": "npm run build && npm run build:umd && npm publish --tag next",
46
47
  "release:zip": "npm run build:all && node src/scripts/create-release-zip.js",
47
- "test": "npx playwright install && wtr --node-resolve",
48
+ "test": "npm run playwright:install && wtr --node-resolve",
48
49
  "test:build": "npm run build:all && npm run test",
49
- "test:compact": "export NYSDS_TEST_OUTPUT=compact && npx playwright install && wtr --node-resolve",
50
- "test:ai": "export NYSDS_TEST_OUTPUT=ai && npx playwright install && wtr --node-resolve",
50
+ "test:compact": "export NYSDS_TEST_OUTPUT=compact && wtr --node-resolve",
51
+ "test:ai": "export NYSDS_TEST_OUTPUT=ai && wtr --node-resolve",
51
52
  "storybook": "cross-env NODE_ENV=production storybook dev -p 6006",
52
53
  "storybook:build:all": "cross-env NODE_ENV=production npm run build:all && npm run storybook",
53
54
  "build-storybook": "npm run build:packages && storybook build",
@@ -56,7 +57,8 @@
56
57
  "clean:node": "rm -rf node_modules && rm -rf packages/*/node_modules && rm -rf packages/**/*/node_modules",
57
58
  "clean:dist": "rm -rf storybook-static && rm -rf coverage && rm -rf packages/*/coverage && rm -rf dist && find packages -type d -name dist ! -path '*/mcp-server/dist' -exec rm -rf {} + 2>/dev/null || true",
58
59
  "clean:turbo": "find packages -type d -name '.turbo' -exec rm -rf {} + && rm -rf .turbo",
59
- "clean:all": "npm run clean:dist && npm run clean:node && find packages -name '*.tsbuildinfo' -delete 2>/dev/null || true && npm run clean:turbo",
60
+ "clean:cache": "rm -rf node_modules/.cache",
61
+ "clean:all": "npm run clean:dist && npm run clean:node && npm run clean:cache && find packages -name '*.tsbuildinfo' -delete 2>/dev/null || true && npm run clean:turbo",
60
62
  "code-connect": "dotenv -- npx figma connect publish",
61
63
  "cem": "npx cem analyze --config ./custom-elements-manifest.config.mjs && cp ./custom-elements.json dist/ && node src/scripts/patch-react-utils.js"
62
64
  },
@@ -91,8 +93,8 @@
91
93
  "@web/test-runner-playwright": "^0.11.1",
92
94
  "cem-plugin-examples": "github:its-hcd/cem-plugin-examples",
93
95
  "cross-env": "^10.1.0",
94
- "custom-element-react-wrappers": "^1.7.3",
95
96
  "custom-element-jsx-integration": "^1.6.0",
97
+ "custom-element-react-wrappers": "^1.7.3",
96
98
  "custom-element-vs-code-integration": "^1.5.0",
97
99
  "dotenv-cli": "^10.0.0",
98
100
  "eslint": "^10.0.0",
@@ -113,6 +115,7 @@
113
115
  "stylelint": "^17.1.1",
114
116
  "stylelint-config-standard": "^40.0.0",
115
117
  "stylelint-config-standard-scss": "^17.0.0",
118
+ "stylelint-prettier": "^5.0.3",
116
119
  "tslib": "^2.8.1",
117
120
  "turbo": "^2.9.3",
118
121
  "typescript": "^5.9.3",
@@ -127,6 +130,7 @@
127
130
  "storybook": "$storybook"
128
131
  },
129
132
  "dependencies": {
133
+ "dompurify": "^3.4.7",
130
134
  "wc-datepicker": "^0.10.0"
131
135
  }
132
136
  }
@@ -21,6 +21,9 @@ export interface NysDividerProps extends Pick<
21
21
  /** Adjusts colors for dark backgrounds. */
22
22
  inverted?: boolean;
23
23
 
24
+ /** If true, the divider will use a lighter color. */
25
+ subtle?: boolean;
26
+
24
27
  /** A space-separated list of the classes of the element. Classes allows CSS and JavaScript to select and access specific elements via the class selectors or functions like the method `Document.getElementsByClassName()`. */
25
28
  className?: string;
26
29
 
@@ -2,7 +2,7 @@ import React, { forwardRef } from "react";
2
2
  import "../../dist/nysds.es.js";
3
3
 
4
4
  export const NysDivider = forwardRef((props, forwardedRef) => {
5
- const { inverted, ...filteredProps } = props;
5
+ const { inverted, subtle, ...filteredProps } = props;
6
6
 
7
7
  return React.createElement(
8
8
  "nys-divider",
@@ -14,6 +14,7 @@ export const NysDivider = forwardRef((props, forwardedRef) => {
14
14
  part: props.part,
15
15
  tabindex: props.tabIndex,
16
16
  inverted: props.inverted ? true : undefined,
17
+ subtle: props.subtle ? true : undefined,
17
18
  style: { ...props.style },
18
19
  },
19
20
  props.children,
@@ -18,9 +18,12 @@ export interface NysIconProps extends Pick<
18
18
  | "onFocus"
19
19
  | "onBlur"
20
20
  > {
21
- /** Icon name from Material Symbols library. Required. */
21
+ /** Icon name to resolve from the selected library. Required. */
22
22
  name?: NysIconElement["name"];
23
23
 
24
+ /** Which registered icon library to use. Defaults to the built-in NYSDS library. */
25
+ library?: NysIconElement["library"];
26
+
24
27
  /** Accessible label. When set, removes `aria-hidden` and adds `aria-label` to the SVG. */
25
28
  ariaLabel?: NysIconElement["ariaLabel"];
26
29
 
@@ -56,11 +59,17 @@ export interface NysIconProps extends Pick<
56
59
 
57
60
  /** Allows developers to make HTML elements focusable, allow or prevent them from being sequentially focusable (usually with the `Tab` key, hence the name) and determine their relative ordering for sequential focus navigation. */
58
61
  tabIndex?: number;
62
+
63
+ /** Resolves when the current icon load (if any) is complete. */
64
+ updateComplete?: NysIconElement["updateComplete"];
59
65
  }
60
66
 
61
67
  /**
62
- * SVG icon from Material Symbols library with size, rotation, and color options.
68
+ * SVG icon with swappable library support, size, rotation, and color options.
63
69
  * ---
64
70
  *
71
+ *
72
+ * ### **Methods:**
73
+ * - **redraw()** - Called by the icon library registry when the current library changes.
65
74
  */
66
75
  export const NysIcon: React.ForwardRefExoticComponent<NysIconProps>;
@@ -1,15 +1,38 @@
1
- import React, { forwardRef } from "react";
1
+ import React, { forwardRef, useRef, useEffect } from "react";
2
2
  import "../../dist/nysds.es.js";
3
+ import { useProperties } from "./react-utils.js";
3
4
 
4
5
  export const NysIcon = forwardRef((props, forwardedRef) => {
5
- const { name, ariaLabel, rotate, flip, color, size, ...filteredProps } =
6
- props;
6
+ const ref = useRef(null);
7
+ const {
8
+ name,
9
+ library,
10
+ ariaLabel,
11
+ rotate,
12
+ flip,
13
+ color,
14
+ size,
15
+ updateComplete,
16
+ ...filteredProps
17
+ } = props;
18
+
19
+ /** Properties - run whenever a property has changed */
20
+ useProperties(ref, "updateComplete", props.updateComplete);
7
21
 
8
22
  return React.createElement(
9
23
  "nys-icon",
10
24
  {
25
+ ref: (node) => {
26
+ ref.current = node;
27
+ if (typeof forwardedRef === "function") {
28
+ forwardedRef(node);
29
+ } else if (forwardedRef) {
30
+ forwardedRef.current = node;
31
+ }
32
+ },
11
33
  ...filteredProps,
12
34
  name: props.name,
35
+ library: props.library,
13
36
  ariaLabel: props.ariaLabel,
14
37
  rotate: props.rotate,
15
38
  flip: props.flip,
@@ -1,11 +1,7 @@
1
1
  import React from "react";
2
- import {
3
- NysRadiobutton as NysRadiobuttonElement,
4
- CustomEvent,
5
- Event,
6
- } from "../../dist/nysds.es.js";
2
+ import { NysRadiobutton as NysRadiobuttonElement } from "../../dist/nysds.es.js";
7
3
 
8
- export type { NysRadiobuttonElement, CustomEvent, Event };
4
+ export type { NysRadiobuttonElement };
9
5
 
10
6
  export interface NysRadiobuttonProps extends Pick<
11
7
  React.AllHTMLAttributes<HTMLElement>,
@@ -82,41 +78,29 @@ export interface NysRadiobuttonProps extends Pick<
82
78
  /** Allows developers to make HTML elements focusable, allow or prevent them from being sequentially focusable (usually with the `Tab` key, hence the name) and determine their relative ordering for sequential focus navigation. */
83
79
  tabIndex?: number;
84
80
 
85
- /** undefined */
86
- onNysErrorClear?: (event: CustomEvent) => void;
87
-
88
81
  /** Fired when selection changes. Detail: `{id, checked, name, value}`. */
89
82
  onNysChange?: (event: CustomEvent) => void;
90
83
 
91
- /** Fired when "other" text input value changes. Detail: `{id, name, value}`. */
92
- onNysOtherInput?: (event: CustomEvent) => void;
93
-
94
84
  /** Fired when radio gains focus. */
95
85
  onNysFocus?: (event: CustomEvent) => void;
96
86
 
97
87
  /** Fired when radio loses focus. */
98
88
  onNysBlur?: (event: CustomEvent) => void;
99
89
 
100
- /** undefined */
101
- onNysError?: (event: CustomEvent) => void;
90
+ /** Fired when "other" text input value changes. Detail: `{id, name, value}`. */
91
+ onNysOtherInput?: (event: CustomEvent) => void;
102
92
  }
103
93
 
104
94
  /**
105
- * Radio button for single selection from mutually exclusive options.
95
+ * Radio button for single selection from mutually exclusive options. This is a READONLY data component.
106
96
  * ---
107
97
  *
108
98
  *
109
99
  * ### **Events:**
110
- * - **nys-error-clear**
111
- * - **nys-change** - Fired when selection changes. Detail: `{id, checked, name, value}`.
112
- * - **nys-other-input** - Fired when "other" text input value changes. Detail: `{id, name, value}`.
100
+ * - **nys-change** - Fired when selection changes. Detail: `{id, checked, name, value}`.
113
101
  * - **nys-focus** - Fired when radio gains focus.
114
102
  * - **nys-blur** - Fired when radio loses focus.
115
- * - **nys-error**
116
- *
117
- * ### **Methods:**
118
- * - **getInputElement(): _Promise<HTMLInputElement | null>_** - Functions
119
- * --------------------------------------------------------------------------
103
+ * - **nys-other-input** - Fired when "other" text input value changes. Detail: `{id, name, value}`.
120
104
  *
121
105
  * ### **Slots:**
122
106
  * - **description** - Custom HTML description content.
@@ -22,12 +22,10 @@ export const NysRadiobutton = forwardRef((props, forwardedRef) => {
22
22
  } = props;
23
23
 
24
24
  /** Event listeners - run once */
25
- useEventListener(ref, "nys-error-clear", props.onNysErrorClear);
26
25
  useEventListener(ref, "nys-change", props.onNysChange);
27
- useEventListener(ref, "nys-other-input", props.onNysOtherInput);
28
26
  useEventListener(ref, "nys-focus", props.onNysFocus);
29
27
  useEventListener(ref, "nys-blur", props.onNysBlur);
30
- useEventListener(ref, "nys-error", props.onNysError);
28
+ useEventListener(ref, "nys-other-input", props.onNysOtherInput);
31
29
 
32
30
  return React.createElement(
33
31
  "nys-radiobutton",
@@ -1,7 +1,10 @@
1
1
  import React from "react";
2
- import { NysRadiogroup as NysRadiogroupElement } from "../../dist/nysds.es.js";
2
+ import {
3
+ NysRadiogroup as NysRadiogroupElement,
4
+ CustomEvent,
5
+ } from "../../dist/nysds.es.js";
3
6
 
4
- export type { NysRadiogroupElement };
7
+ export type { NysRadiogroupElement, CustomEvent };
5
8
 
6
9
  export interface NysRadiogroupProps extends Pick<
7
10
  React.AllHTMLAttributes<HTMLElement>,
@@ -30,6 +33,9 @@ export interface NysRadiogroupProps extends Pick<
30
33
  /** Renders all radiobuttons as tiles with larger clickable area. */
31
34
  tile?: boolean;
32
35
 
36
+ /** undefined */
37
+ _showOtherError?: boolean;
38
+
33
39
  /** Unique identifier. Auto-generated if not provided. */
34
40
  id?: NysRadiogroupElement["id"];
35
41
 
@@ -74,6 +80,12 @@ export interface NysRadiogroupProps extends Pick<
74
80
 
75
81
  /** Allows developers to make HTML elements focusable, allow or prevent them from being sequentially focusable (usually with the `Tab` key, hence the name) and determine their relative ordering for sequential focus navigation. */
76
82
  tabIndex?: number;
83
+
84
+ /** undefined */
85
+ onNysChange?: (event: CustomEvent) => void;
86
+
87
+ /** undefined */
88
+ onNysOtherInput?: (event: CustomEvent) => void;
77
89
  }
78
90
 
79
91
  /**
@@ -81,6 +93,10 @@ export interface NysRadiogroupProps extends Pick<
81
93
  * ---
82
94
  *
83
95
  *
96
+ * ### **Events:**
97
+ * - **nys-change**
98
+ * - **nys-other-input**
99
+ *
84
100
  * ### **Slots:**
85
101
  * - _default_ - Default slot for `nys-radiobutton` elements.
86
102
  * - **description** - Custom HTML description content.
@@ -1,12 +1,15 @@
1
- import React, { forwardRef } from "react";
1
+ import React, { forwardRef, useRef, useEffect } from "react";
2
2
  import "../../dist/nysds.es.js";
3
+ import { useEventListener } from "./react-utils.js";
3
4
 
4
5
  export const NysRadiogroup = forwardRef((props, forwardedRef) => {
6
+ const ref = useRef(null);
5
7
  const {
6
8
  required,
7
9
  optional,
8
10
  showError,
9
11
  tile,
12
+ _showOtherError,
10
13
  id,
11
14
  name,
12
15
  errorMessage,
@@ -18,9 +21,21 @@ export const NysRadiogroup = forwardRef((props, forwardedRef) => {
18
21
  ...filteredProps
19
22
  } = props;
20
23
 
24
+ /** Event listeners - run once */
25
+ useEventListener(ref, "nys-change", props.onNysChange);
26
+ useEventListener(ref, "nys-other-input", props.onNysOtherInput);
27
+
21
28
  return React.createElement(
22
29
  "nys-radiogroup",
23
30
  {
31
+ ref: (node) => {
32
+ ref.current = node;
33
+ if (typeof forwardedRef === "function") {
34
+ forwardedRef(node);
35
+ } else if (forwardedRef) {
36
+ forwardedRef.current = node;
37
+ }
38
+ },
24
39
  ...filteredProps,
25
40
  id: props.id,
26
41
  name: props.name,
@@ -39,6 +54,7 @@ export const NysRadiogroup = forwardRef((props, forwardedRef) => {
39
54
  optional: props.optional ? true : undefined,
40
55
  showError: props.showError ? true : undefined,
41
56
  tile: props.tile ? true : undefined,
57
+ _showOtherError: props._showOtherError ? true : undefined,
42
58
  style: { ...props.style },
43
59
  },
44
60
  props.children,