@enonic/ui 0.22.1 → 0.23.0

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 (31) hide show
  1. package/dist/enonic-ui.cjs +1 -1
  2. package/dist/enonic-ui.es.js +79 -80
  3. package/dist/styles/preset.css +1 -1
  4. package/dist/styles/style.css +1 -1
  5. package/dist/styles/tokens.css +1 -1
  6. package/dist/types/components/avatar/avatar.d.ts +1 -1
  7. package/dist/types/components/button/button.d.ts +1 -1
  8. package/dist/types/components/combobox/combobox.d.ts +3 -2
  9. package/dist/types/components/combobox/index.d.ts +1 -1
  10. package/dist/types/components/icon-button/icon-button.d.ts +3 -3
  11. package/dist/types/components/index.d.ts +1 -1
  12. package/dist/types/components/link/link.d.ts +1 -1
  13. package/dist/types/components/list-item/index.d.ts +1 -1
  14. package/dist/types/components/listbox/index.d.ts +1 -1
  15. package/dist/types/components/listbox/listbox.d.ts +1 -1
  16. package/dist/types/components/menu/index.d.ts +1 -1
  17. package/dist/types/components/menubar/index.d.ts +1 -1
  18. package/dist/types/components/search-field/search-field.d.ts +1 -1
  19. package/dist/types/components/selectable-list-item/selectable-list-item.d.ts +1 -1
  20. package/dist/types/components/toast/index.d.ts +1 -1
  21. package/dist/types/components/toast/toast.d.ts +1 -1
  22. package/dist/types/components/toggle-group/index.d.ts +1 -1
  23. package/dist/types/components/toggle-group/toggle-group.d.ts +1 -1
  24. package/dist/types/components/toolbar/toolbar-toggle-group.d.ts +1 -1
  25. package/dist/types/components/tree-list/index.d.ts +1 -1
  26. package/dist/types/components/tree-list/tree-list.d.ts +2 -2
  27. package/dist/types/hooks/index.d.ts +7 -7
  28. package/dist/types/hooks/use-controlled-state-with-null.d.ts +19 -2
  29. package/dist/types/hooks/use-controlled-state.d.ts +23 -8
  30. package/dist/types/providers/tree-list-provider.d.ts +1 -1
  31. package/package.json +72 -60
@@ -1,3 +1,4 @@
1
+ import { SetStateAction } from 'react';
1
2
  /**
2
3
  * Manages state that can be either controlled or uncontrolled.
3
4
  * Follows the React pattern for controlled/uncontrolled state management.
@@ -8,7 +9,9 @@
8
9
  * @param defaultValue - The default value for uncontrolled mode (e.g., `defaultValue`, `defaultOpen`)
9
10
  * @param onChange - Callback invoked when the value changes
10
11
  *
11
- * @returns A tuple containing the current value and a setter function
12
+ * @returns A tuple containing the current value and a setter function.
13
+ * The setter accepts either a direct value or an updater function `(prev) => next`,
14
+ * matching React's `useState` API. The setter reference is stable across renders.
12
15
  *
13
16
  * **Controlled vs Uncontrolled Detection:**
14
17
  * - `undefined` = uncontrolled mode (prop not provided)
@@ -20,6 +23,10 @@
20
23
  * - `active="item-1"` → controlled with active item
21
24
  * - `active` not provided → uncontrolled mode
22
25
  *
26
+ * **Note on function values:**
27
+ * If `T` is a function type, you must wrap the value in an updater function
28
+ * to avoid it being interpreted as an updater: `setValue(() => myFunction)`.
29
+ *
23
30
  * @example
24
31
  * ```tsx
25
32
  * // Uncontrolled usage
@@ -34,13 +41,21 @@
34
41
  * return <div>{value ? 'Open' : 'Closed'}</div>;
35
42
  * }
36
43
  *
37
- * // Controlled with null support (for "no value" state)
38
- * function Component({ active, onActiveChange }: { active?: string | null }) {
39
- * const [value, setValue] = useControlledState(active, undefined, onActiveChange);
40
- * // active={null} controlled, value = null
41
- * // active="item" controlled, value = "item"
42
- * // active not provided uncontrolled, value from defaultActive
44
+ * // Using updater function (safe for batched updates)
45
+ * function Counter() {
46
+ * const [count, setCount] = useControlledState(undefined, 0);
47
+ * const incrementTwice = () => {
48
+ * setCount(prev => prev + 1);
49
+ * setCount(prev => prev + 1); // Correctly results in +2
50
+ * };
51
+ * return <button onClick={incrementTwice}>{count}</button>;
52
+ * }
53
+ *
54
+ * // Toggle pattern
55
+ * function Toggle() {
56
+ * const [pressed, setPressed] = useControlledState(undefined, false);
57
+ * return <button onClick={() => setPressed(prev => !prev)}>{pressed ? 'On' : 'Off'}</button>;
43
58
  * }
44
59
  * ```
45
60
  */
46
- export declare function useControlledState<T>(controlledValue: T | undefined, defaultValue: T, onChange?: (value: T) => void): [T, (value: T) => void];
61
+ export declare function useControlledState<T>(controlledValue: T | undefined, defaultValue: T, onChange?: (value: T) => void): [T, (action: SetStateAction<T>) => void];
@@ -1,5 +1,5 @@
1
- import { TreeNode } from '../components/tree-list/tree-list';
2
1
  import { ReactElement, ReactNode } from 'react';
2
+ import { TreeNode } from '../components/tree-list/tree-list';
3
3
  export type TreeListContextValue<T extends TreeNode = TreeNode> = {
4
4
  baseId: string;
5
5
  items: readonly T[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enonic/ui",
3
- "version": "0.22.1",
3
+ "version": "0.23.0",
4
4
  "description": "Enonic UI Component Library",
5
5
  "author": "Enonic",
6
6
  "license": "MIT",
@@ -12,6 +12,10 @@
12
12
  "bugs": {
13
13
  "url": "https://github.com/enonic/npm-enonic-ui/issues"
14
14
  },
15
+ "publishConfig": {
16
+ "access": "public",
17
+ "provenance": false
18
+ },
15
19
  "keywords": [
16
20
  "enonic",
17
21
  "ui",
@@ -43,6 +47,35 @@
43
47
  "./base.css": "./dist/styles/base.css",
44
48
  "./utilities.css": "./dist/styles/utilities.css"
45
49
  },
50
+ "scripts": {
51
+ "build": "pnpm clean && pnpm build:ui",
52
+ "build:ui": "pnpm --color /^build:ui:.*$/",
53
+ "build:ui:lib": "vite build --config vite.config.ts",
54
+ "build:ui:css": "vite build --config vite.config.css.ts",
55
+ "build:storybook": "storybook build",
56
+ "build:all": "pnpm build && pnpm build:storybook",
57
+ "dev": "storybook dev -p 6006",
58
+ "clean": "rm -rf dist coverage reports storybook-static",
59
+ "check": "pnpm typecheck && pnpm lint && pnpm format:check",
60
+ "typecheck": "pnpm typecheck:app && pnpm typecheck:node",
61
+ "typecheck:app": "tsc --noEmit --project tsconfig.app.json",
62
+ "typecheck:node": "tsc --noEmit --project tsconfig.node.json",
63
+ "lint": "biome check . && eslint --cache '**/*.{ts,tsx}' --max-warnings 0 --concurrency auto",
64
+ "lint:fix": "biome check --write --unsafe . && eslint --cache 'src/**/*.{ts,tsx}' --fix --concurrency auto",
65
+ "lint:ci": "biome check . && eslint --no-cache 'src/**/*.{ts,tsx}' --max-warnings 0 --concurrency auto",
66
+ "format": "biome format --write .",
67
+ "format:check": "biome format .",
68
+ "test": "exit 0",
69
+ "test:ci": "exit 0",
70
+ "prepack": "echo 'Packaging...'",
71
+ "prepublishOnly": "pnpm check && pnpm build && pnpm size",
72
+ "release": "npm publish --access public",
73
+ "release:dry": "pnpm publish --dry-run --no-git-checks",
74
+ "analyze": "pnpm build && open dist/stats.html",
75
+ "size": "size-limit",
76
+ "preview": "pnpm dlx serve . -p 4000",
77
+ "prepare": "husky"
78
+ },
46
79
  "dependencies": {
47
80
  "class-variance-authority": "~0.7.1",
48
81
  "clsx": "~2.1.1",
@@ -68,47 +101,50 @@
68
101
  }
69
102
  },
70
103
  "devDependencies": {
104
+ "@biomejs/biome": "~2.3.8",
71
105
  "@chromatic-com/storybook": "~4.1.3",
72
106
  "@eslint/js": "~9.39.1",
73
107
  "@preact/preset-vite": "~2.10.2",
74
- "@size-limit/file": "~11.2.0",
75
- "@size-limit/preset-small-lib": "~11.2.0",
76
- "@storybook/addon-a11y": "~10.0.8",
77
- "@storybook/addon-docs": "~10.0.8",
78
- "@storybook/addon-links": "~10.0.8",
79
- "@storybook/addon-themes": "~10.0.8",
80
- "@storybook/preact-vite": "~10.0.8",
108
+ "@size-limit/file": "~12.0.0",
109
+ "@size-limit/preset-small-lib": "~12.0.0",
110
+ "@storybook/addon-a11y": "~10.1.2",
111
+ "@storybook/addon-docs": "~10.1.2",
112
+ "@storybook/addon-links": "~10.1.2",
113
+ "@storybook/addon-themes": "~10.1.2",
114
+ "@storybook/preact-vite": "~10.1.2",
81
115
  "@tailwindcss/vite": "~4.1.17",
82
- "@trivago/prettier-plugin-sort-imports": "~6.0.0",
83
116
  "@types/node": "~24.10.1",
84
- "@types/react": "~19.2.6",
117
+ "@types/react": "~19.2.7",
85
118
  "@types/react-dom": "~19.2.3",
86
- "@typescript-eslint/eslint-plugin": "~8.47.0",
87
- "@typescript-eslint/parser": "~8.47.0",
119
+ "@typescript-eslint/eslint-plugin": "~8.48.0",
120
+ "@typescript-eslint/parser": "~8.48.0",
88
121
  "eslint": "~9.39.1",
89
- "eslint-import-resolver-typescript": "~4.4.4",
90
- "eslint-plugin-import": "~2.32.0",
91
122
  "eslint-plugin-jsx-a11y": "~6.10.2",
92
123
  "eslint-plugin-react": "~7.37.5",
93
- "eslint-plugin-react-hooks": "~7.0.1",
94
124
  "husky": "~9.1.7",
95
125
  "lint-staged": "~16.2.7",
96
- "lucide-preact": "~0.554.0",
97
- "lucide-react": "~0.554.0",
126
+ "lucide-preact": "~0.555.0",
127
+ "lucide-react": "~0.555.0",
98
128
  "postcss": "~8.5.6",
99
- "prettier": "~3.6.2",
100
129
  "rollup-plugin-visualizer": "~6.0.5",
101
- "size-limit": "~11.2.0",
102
- "storybook": "~10.0.8",
130
+ "size-limit": "~12.0.0",
131
+ "storybook": "~10.1.2",
103
132
  "tailwindcss": "~4.1.17",
104
133
  "terser": "~5.44.1",
105
134
  "tw-animate-css": "~1.4.0",
106
135
  "typescript": "~5.9.3",
107
- "typescript-eslint": "~8.47.0",
108
- "vite": "~7.2.2",
136
+ "typescript-eslint": "~8.48.0",
137
+ "vite": "~7.2.6",
109
138
  "vite-plugin-dts": "~4.5.4",
110
139
  "vite-plugin-environment": "~1.1.3"
111
140
  },
141
+ "pnpm": {
142
+ "ignoredBuiltDependencies": [
143
+ "@tailwindcss/oxide",
144
+ "esbuild",
145
+ "unrs-resolver"
146
+ ]
147
+ },
112
148
  "browserslist": {
113
149
  "production": [
114
150
  ">0.2%",
@@ -122,60 +158,36 @@
122
158
  ]
123
159
  },
124
160
  "engines": {
125
- "node": ">=22.19.5",
126
- "pnpm": ">=10.17.0",
127
- "npm": ">=10.9.3"
161
+ "node": ">=24.11.1",
162
+ "pnpm": ">=10.24.0",
163
+ "npm": ">=11.6.2"
128
164
  },
165
+ "packageManager": "pnpm@10.24.0",
129
166
  "lint-staged": {
130
- "src/**/*.{js,jsx,ts,tsx}": [
131
- "eslint --fix --max-warnings 0",
132
- "prettier --write"
167
+ "*.{ts,tsx}": [
168
+ "biome check --write --unsafe --no-errors-on-unmatched",
169
+ "eslint --cache --fix --no-warn-ignored --concurrency auto"
133
170
  ],
134
- "**/*.{json,md,yml,yaml} !pnpm-lock.yaml": [
135
- "prettier --write"
171
+ "*.{json,css}": [
172
+ "biome check --write --unsafe --no-errors-on-unmatched"
136
173
  ]
137
174
  },
138
175
  "size-limit": [
139
176
  {
140
177
  "path": "dist/enonic-ui.es.js",
141
- "limit": "30 KB"
178
+ "limit": "35 KB"
142
179
  },
143
180
  {
144
181
  "path": "dist/enonic-ui.cjs",
145
- "limit": "30 KB"
182
+ "limit": "35 KB"
146
183
  },
147
184
  {
148
185
  "path": "dist/styles/style.css",
149
- "limit": "10 KB"
186
+ "limit": "12 KB"
150
187
  },
151
188
  {
152
189
  "path": "dist/styles/preset.css",
153
190
  "limit": "2 KB"
154
191
  }
155
- ],
156
- "scripts": {
157
- "build": "pnpm clean && pnpm build:ui",
158
- "build:ui": "pnpm --color /^build:ui:.*$/",
159
- "build:ui:lib": "vite build --config vite.config.ts",
160
- "build:ui:css": "vite build --config vite.config.css.ts",
161
- "build:storybook": "storybook build",
162
- "build:all": "pnpm build && pnpm build:storybook",
163
- "dev": "storybook dev -p 6006",
164
- "clean": "rm -rf dist coverage reports storybook-static",
165
- "check": "pnpm typecheck && pnpm lint && pnpm format:check",
166
- "typecheck": "pnpm typecheck:app && pnpm typecheck:node",
167
- "typecheck:app": "tsc --noEmit --project tsconfig.app.json",
168
- "typecheck:node": "tsc --noEmit --project tsconfig.node.json",
169
- "lint": "eslint --no-cache '**/*.{js,jsx,ts,tsx}' --max-warnings 0",
170
- "lint:fix": "eslint --cache '**/*.{js,jsx,ts,tsx}' --fix",
171
- "format": "prettier --write '**/*.{js,jsx,ts,tsx,json,md,yml,yaml}' !pnpm-lock.yaml --log-level warn",
172
- "format:check": "prettier --check '**/*.{js,jsx,ts,tsx,json,md,yml,yaml}' !pnpm-lock.yaml --log-level warn",
173
- "test": "exit 0",
174
- "test:ci": "exit 0",
175
- "release": "pnpm publish --access public --no-git-checks",
176
- "release:dry": "pnpm publish --dry-run --access public --no-git-checks",
177
- "analyze": "pnpm build && open dist/stats.html",
178
- "size": "size-limit",
179
- "preview": "pnpm dlx serve . -p 4000"
180
- }
181
- }
192
+ ]
193
+ }