@nysds/components 1.20.0-alpha-2 → 1.20.0-alpha-3

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.
@@ -6,12 +6,17 @@ import "./nys-fileitem";
6
6
  *
7
7
  * Use for document uploads, image uploads, or any file submission. Enable `dropzone` for drag-and-drop UI.
8
8
  *
9
+ * Read or write the current selection via the `files` (`File[]`) and `value` (`File | null`)
10
+ * properties — useful for rehydrating state or binding from a framework form model.
11
+ * Setting them is silent (does not emit `nys-change`).
12
+ *
9
13
  * @summary File input with drag-and-drop, validation, and progress tracking.
10
14
  * @element nys-fileinput
11
15
  *
12
16
  * @slot description - Custom HTML description content.
13
17
  *
14
18
  * @fires nys-change - Fired when files are added or removed. Detail: `{id, files}`.
19
+ * @fires nys-blur - Fired when focus leaves the component. Triggers validation.
15
20
  *
16
21
  * @example Single file upload
17
22
  * ```html
@@ -69,6 +74,28 @@ export declare class NysFileinput extends LitElement {
69
74
  /** Adjusts colors for dark backgrounds. */
70
75
  inverted: boolean;
71
76
  private _selectedFiles;
77
+ /**
78
+ * The currently selected files. Read to get the current selection; set to
79
+ * replace it (e.g. rehydrating state after navigation, or binding from a
80
+ * framework form model). Property-only — a `File[]` cannot round-trip through
81
+ * an HTML attribute. Setting this is silent (does not emit `nys-change`),
82
+ * matching native input behavior and avoiding feedback loops in two-way bindings.
83
+ */
84
+ get files(): File[];
85
+ set files(incoming: File[]);
86
+ /**
87
+ * Single-file convenience accessor (parity with `nys-textinput`'s `value`).
88
+ * Reads the first selected file (or `null`); setting replaces the selection.
89
+ */
90
+ get value(): File | null;
91
+ set value(file: File | null);
92
+ /**
93
+ * Programmatically set the selection and await async validation/processing.
94
+ * Same as assigning `files`, but resolves once every file has finished its
95
+ * magic-byte validation and read — use when you need to read `checkValidity()`
96
+ * or the settled selection immediately after.
97
+ */
98
+ setFiles(incoming: File[]): Promise<void>;
72
99
  private _dragActive;
73
100
  private get _isDropDisabled();
74
101
  private get _buttonAriaLabel();
@@ -101,6 +128,7 @@ export declare class NysFileinput extends LitElement {
101
128
  */
102
129
  private _saveSelectedFiles;
103
130
  private _processFile;
131
+ private _handleBlur;
104
132
  private _dispatchChangeEvent;
105
133
  private _openFileDialog;
106
134
  private _handlePostFileSelectionFocus;
@@ -9,6 +9,7 @@ import { LitElement } from "lit";
9
9
  * @element nys-globalheader
10
10
  *
11
11
  * @slot - Navigation content (typically `<ul>` with `<li><a>` links). Auto-sanitized.
12
+ * @slot user-actions - User-account controls (e.g. profile link, settings, log-out button) shown in the header.
12
13
  *
13
14
  * @example Basic header
14
15
  * ```html
@@ -25,7 +26,13 @@ export declare class NysGlobalHeader extends LitElement {
25
26
  agencyName: string;
26
27
  /** URL for the header title link. If empty, title is not clickable. */
27
28
  homepageLink: string;
28
- /** Toggles the NYS brand mark */
29
+ /**
30
+ * Displays the NYS brand mark in the header. Off by default.
31
+ *
32
+ * Enable only for internal, state-employee (back-office) applications that omit
33
+ * `nys-unavheader`. Any resident-facing app — even one requiring login — should
34
+ * keep `nys-unavheader` for trust and leave this off.
35
+ */
29
36
  nysLogo: boolean;
30
37
  /** Internal state to track mobile menu open/closed status. */
31
38
  private _isMobileMenuOpen;
@@ -1,18 +1,11 @@
1
1
  /**
2
2
  * Icon Cache
3
3
  *
4
- * Shared SVG sanitize/parse pipeline and caches. URL-based icons (custom
5
- * libraries) are fetched once per URL; inline SVG sources (the built-in
6
- * NYSDS set) are parsed once per source string. Each consumer gets a
7
- * cloned SVGElement via `cloneNode(true)` so DOM nodes are never shared.
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.
8
7
  */
9
8
  /** Fetch and parse an SVG from a URL. Returns a cloned SVGElement (safe for multiple consumers). */
10
9
  export declare function fetchIcon(url: string): Promise<SVGElement>;
11
- /**
12
- * Parse an inline SVG source string. Results are cached by source content,
13
- * so repeated renders of the same icon sanitize/parse once. Returns a
14
- * cloned SVGElement (safe for multiple consumers).
15
- */
16
- export declare function parseIcon(source: string): SVGElement;
17
- /** Clear one URL entry, or all cached icons (URL and inline) when no URL is given. */
10
+ /** Clear one or all entries from the cache. */
18
11
  export declare function clearIconCache(url?: string): void;
@@ -1,51 +1,33 @@
1
1
  /**
2
2
  * Icon Library Registry
3
3
  *
4
- * Global registry for icon libraries. The "default" library resolves the
5
- * standard NYSDS icon set from an inline SVG map shipped as JavaScript
6
- * (`nys-icon.library.ts`), loaded lazily as a separate chunk no base-URL
7
- * discovery, no per-icon fetch, no browser globals. Custom libraries
8
- * (Font Awesome, Material Icons, etc.) register at runtime via
9
- * `registerIconLibrary()` and typically resolve to URLs.
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()`.
10
8
  *
11
- * The registry and watcher maps are stored on `globalThis` so that even
9
+ * The registry and watcher maps are stored on `window` so that even
12
10
  * when bundlers (Storybook Vite, etc.) create duplicate module
13
- * instances, every copy shares a single source of truth. `globalThis`
14
- * (rather than `window`) keeps module import side-effect-safe in
15
- * Node/SSR environments, where `window` does not exist.
11
+ * instances, every copy shares a single source of truth.
16
12
  */
17
- /**
18
- * How a resolver locates an icon: a URL string (legacy shorthand for
19
- * `{ type: "url" }`), an explicit URL, or inline SVG source. Resolvers may
20
- * return synchronously or via a Promise.
21
- */
22
- export type IconResolution = string | {
23
- type: "url";
24
- href: string;
25
- } | {
26
- type: "svg";
27
- content: string;
28
- };
29
13
  export interface IconLibrary {
30
- /** Given an icon name, return where/what its SVG is. Return undefined if not found. */
31
- resolver: (name: string) => IconResolution | undefined | Promise<IconResolution | undefined>;
32
- /** Optional post-parse transform applied to the SVGElement. */
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. */
33
17
  mutator?: (svg: SVGElement) => void;
34
18
  }
35
19
  export interface NysIconWatcher {
36
20
  redraw(): void;
37
21
  }
22
+ interface NysIconGlobals {
23
+ __nysIconRegistry: Map<string, IconLibrary>;
24
+ __nysIconWatchers: Map<string, Set<NysIconWatcher>>;
25
+ }
38
26
  declare global {
39
- var __nysIconRegistry: Map<string, IconLibrary> | undefined;
40
- var __nysIconWatchers: Map<string, Set<NysIconWatcher>> | undefined;
41
- var __nysIconDefaultRegistered: boolean | undefined;
27
+ interface Window extends NysIconGlobals {
28
+ }
42
29
  }
43
30
  /** Register or replace a named icon library. All watching icons using this library will redraw.
44
- *
45
- * Intended for custom/external libraries — the standard NYSDS set is
46
- * built in and needs no registration. Registering under `"default"`
47
- * replaces the built-in set (escape hatch).
48
- *
49
31
  * @example Register a Font Awesome library with a custom resolver:
50
32
  * ```ts
51
33
  * registerIconLibrary("fa", {
@@ -62,3 +44,4 @@ export declare function getIconLibrary(name: string): IconLibrary | undefined;
62
44
  export declare function watchIconLibrary(name: string, watcher: NysIconWatcher): void;
63
45
  /** Unsubscribe an icon instance from library change notifications. */
64
46
  export declare function unwatchIconLibrary(name: string, watcher: NysIconWatcher): void;
47
+ export {};
@@ -1,4 +1,4 @@
1
1
  export * from "./nys-icon";
2
- export { registerIconLibrary, unregisterIconLibrary, getIconLibrary, } from "./icon-library-registry";
3
- export type { IconLibrary, IconResolution } from "./icon-library-registry";
2
+ export { registerIconLibrary, unregisterIconLibrary, } from "./icon-library-registry";
3
+ export type { IconLibrary } from "./icon-library-registry";
4
4
  export { clearIconCache } from "./icon-cache";
@@ -8,6 +8,10 @@ import { LitElement } from "lit";
8
8
  *
9
9
  * @summary Universal NYS header with trust bar, search, and translation. Required site-wide.
10
10
  * @element nys-unavheader
11
+ *
12
+ * @fires nys-language-select - Fired when a language is selected. Detail: `{language: {code, label, url?}}`. Cancelable; `preventDefault()` overrides the default Smartling redirect.
13
+ * @fires nys-search-submit - Fired when a search is submitted. Detail: `{query}`. Cancelable; `preventDefault()` overrides the default search redirect.
14
+
11
15
  *
12
16
  * @example Standard usage
13
17
  * ```html
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/components",
3
- "version": "1.20.0-alpha-2",
3
+ "version": "1.20.0-alpha-3",
4
4
  "description": "New York State's design system and code component library.",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -47,8 +47,7 @@
47
47
  "release:zip": "npm run build:all && node src/scripts/create-release-zip.js",
48
48
  "pretest": "playwright install",
49
49
  "test": "wtr --node-resolve",
50
- "test:ssr": "node scripts/test-ssr.mjs && node scripts/audit-dist.mjs",
51
- "audit:dist": "node scripts/audit-dist.mjs",
50
+ "test:ssr": "node scripts/test-ssr.mjs",
52
51
  "test:build": "npm run build:all && npm run test",
53
52
  "test:compact": "export NYSDS_TEST_OUTPUT=compact && wtr --node-resolve",
54
53
  "test:ai": "export NYSDS_TEST_OUTPUT=ai && wtr --node-resolve",
@@ -137,5 +136,8 @@
137
136
  "dompurify": "^3.4.7",
138
137
  "wc-datepicker": "^0.10.0"
139
138
  },
140
- "sideEffects": true
139
+ "sideEffects": true,
140
+ "peerDependencies": {
141
+ "lit": "^3.3.1"
142
+ }
141
143
  }
@@ -1,10 +1,11 @@
1
1
  import React from "react";
2
2
  import {
3
3
  NysFileinput as NysFileinputElement,
4
+ Event,
4
5
  CustomEvent,
5
6
  } from "../../dist/nysds.es.js";
6
7
 
7
- export type { NysFileinputElement, CustomEvent };
8
+ export type { NysFileinputElement, Event, CustomEvent };
8
9
 
9
10
  export interface NysFileinputProps extends Pick<
10
11
  React.AllHTMLAttributes<HTMLElement>,
@@ -90,6 +91,20 @@ export interface NysFileinputProps extends Pick<
90
91
  /** 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. */
91
92
  tabIndex?: number;
92
93
 
94
+ /** The currently selected files. Read to get the current selection; set to
95
+ replace it (e.g. rehydrating state after navigation, or binding from a
96
+ framework form model). Property-only — a `File[]` cannot round-trip through
97
+ an HTML attribute. Setting this is silent (does not emit `nys-change`),
98
+ matching native input behavior and avoiding feedback loops in two-way bindings. */
99
+ files?: NysFileinputElement["files"];
100
+
101
+ /** Single-file convenience accessor (parity with `nys-textinput`'s `value`).
102
+ Reads the first selected file (or `null`); setting replaces the selection. */
103
+ value?: NysFileinputElement["value"];
104
+
105
+ /** Fired when focus leaves the component. Triggers validation. */
106
+ onNysBlur?: (event: CustomEvent) => void;
107
+
93
108
  /** Fired when files are added or removed. Detail: `{id, files}`. */
94
109
  onNysChange?: (event: CustomEvent) => void;
95
110
  }
@@ -100,7 +115,14 @@ export interface NysFileinputProps extends Pick<
100
115
  *
101
116
  *
102
117
  * ### **Events:**
103
- * - **nys-change** - Fired when files are added or removed. Detail: `{id, files}`.
118
+ * - **nys-blur** - Fired when focus leaves the component. Triggers validation.
119
+ * - **nys-change** - Fired when files are added or removed. Detail: `{id, files}`.
120
+ *
121
+ * ### **Methods:**
122
+ * - **setFiles(incoming: _File[]_): _Promise<void>_** - Programmatically set the selection and await async validation/processing.
123
+ * Same as assigning `files`, but resolves once every file has finished its
124
+ * magic-byte validation and read — use when you need to read `checkValidity()`
125
+ * or the settled selection immediately after.
104
126
  *
105
127
  * ### **Slots:**
106
128
  * - **description** - Custom HTML description content.
@@ -1,6 +1,6 @@
1
1
  import React, { forwardRef, useRef, useEffect } from "react";
2
2
  import "../../dist/nysds.es.js";
3
- import { useEventListener } from "./react-utils.js";
3
+ import { useEventListener, useProperties } from "./react-utils.js";
4
4
 
5
5
  export const NysFileinput = forwardRef((props, forwardedRef) => {
6
6
  const ref = useRef(null);
@@ -21,12 +21,19 @@ export const NysFileinput = forwardRef((props, forwardedRef) => {
21
21
  accept,
22
22
  errorMessage,
23
23
  width,
24
+ files,
25
+ value,
24
26
  ...filteredProps
25
27
  } = props;
26
28
 
27
29
  /** Event listeners - run once */
30
+ useEventListener(ref, "nys-blur", props.onNysBlur);
28
31
  useEventListener(ref, "nys-change", props.onNysChange);
29
32
 
33
+ /** Properties - run whenever a property has changed */
34
+ useProperties(ref, "files", props.files);
35
+ useProperties(ref, "value", props.value);
36
+
30
37
  return React.createElement(
31
38
  "nys-fileinput",
32
39
  {
@@ -18,7 +18,11 @@ export interface NysGlobalHeaderProps extends Pick<
18
18
  | "onFocus"
19
19
  | "onBlur"
20
20
  > {
21
- /** Toggles the NYS brand mark */
21
+ /** Displays the NYS brand mark in the header. Off by default.
22
+
23
+ Enable only for internal, state-employee (back-office) applications that omit
24
+ `nys-unavheader`. Any resident-facing app — even one requiring login — should
25
+ keep `nys-unavheader` for trust and leave this off. */
22
26
  nysLogo?: boolean;
23
27
 
24
28
  /** Application name displayed prominently. */
@@ -59,5 +63,6 @@ export interface NysGlobalHeaderProps extends Pick<
59
63
  *
60
64
  * ### **Slots:**
61
65
  * - _default_ - Navigation content (typically `<ul>` with `<li><a>` links). Auto-sanitized.
66
+ * - **user-actions** - User-account controls (e.g. profile link, settings, log-out button) shown in the header.
62
67
  */
63
68
  export const NysGlobalHeader: React.ForwardRefExoticComponent<NysGlobalHeaderProps>;
@@ -498,7 +498,17 @@ export type NysFileinputProps = {
498
498
  width?: "lg" | "full";
499
499
  /** Adjusts colors for dark backgrounds. */
500
500
  inverted?: boolean;
501
-
501
+ /** The currently selected files. Read to get the current selection; set to
502
+ replace it (e.g. rehydrating state after navigation, or binding from a
503
+ framework form model). Property-only — a `File[]` cannot round-trip through
504
+ an HTML attribute. Setting this is silent (does not emit `nys-change`),
505
+ matching native input behavior and avoiding feedback loops in two-way bindings. */
506
+ files?: File[];
507
+ /** Single-file convenience accessor (parity with `nys-textinput`'s `value`).
508
+ Reads the first selected file (or `null`); setting replaces the selection. */
509
+ value?: File | null;
510
+ /** Fired when focus leaves the component. Triggers validation. */
511
+ "onnys-blur"?: (e: CustomEvent<Event>) => void;
502
512
  /** Fired when files are added or removed. Detail: `{id, files}`. */
503
513
  "onnys-change"?: (e: CustomEvent<CustomEvent>) => void;
504
514
  };
@@ -533,7 +543,11 @@ export type NysGlobalHeaderProps = {
533
543
  agencyName?: string;
534
544
  /** URL for the header title link. If empty, title is not clickable. */
535
545
  homepageLink?: string;
536
- /** Toggles the NYS brand mark */
546
+ /** Displays the NYS brand mark in the header. Off by default.
547
+
548
+ Enable only for internal, state-employee (back-office) applications that omit
549
+ `nys-unavheader`. Any resident-facing app — even one requiring login — should
550
+ keep `nys-unavheader` for trust and leave this off. */
537
551
  nysLogo?: boolean;
538
552
  };
539
553
 
@@ -1271,7 +1285,14 @@ export type CustomElements = {
1271
1285
  *
1272
1286
  *
1273
1287
  * ### **Events:**
1274
- * - **nys-change** - Fired when files are added or removed. Detail: `{id, files}`.
1288
+ * - **nys-blur** - Fired when focus leaves the component. Triggers validation.
1289
+ * - **nys-change** - Fired when files are added or removed. Detail: `{id, files}`.
1290
+ *
1291
+ * ### **Methods:**
1292
+ * - **setFiles(incoming: _File[]_): _Promise<void>_** - Programmatically set the selection and await async validation/processing.
1293
+ * Same as assigning `files`, but resolves once every file has finished its
1294
+ * magic-byte validation and read — use when you need to read `checkValidity()`
1295
+ * or the settled selection immediately after.
1275
1296
  *
1276
1297
  * ### **Slots:**
1277
1298
  * - **description** - Custom HTML description content.
@@ -1305,6 +1326,7 @@ export type CustomElements = {
1305
1326
  *
1306
1327
  * ### **Slots:**
1307
1328
  * - _default_ - Navigation content (typically `<ul>` with `<li><a>` links). Auto-sanitized.
1329
+ * - **user-actions** - User-account controls (e.g. profile link, settings, log-out button) shown in the header.
1308
1330
  */
1309
1331
  "nys-globalheader": Partial<NysGlobalHeaderProps & BaseProps & BaseEvents>;
1310
1332