aeon-ui-engine 1.4.0 → 1.5.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.
- package/CHANGELOG.md +27 -0
- package/CONSUMER.md +67 -27
- package/INTEGRATION.md +1 -1
- package/README.md +17 -8
- package/package.json +4 -1
- package/packages/cli/dist/bin.js +29 -3
- package/packages/cli/dist/{chunk-5L47SLNV.js → chunk-JMNRJCWF.js} +63 -9
- package/packages/cli/dist/index.d.ts +15 -1
- package/packages/cli/dist/index.js +3 -1
- package/packages/cli/src/bin.ts +30 -2
- package/packages/cli/src/index.ts +1 -0
- package/packages/cli/src/init.ts +10 -4
- package/packages/cli/src/link.ts +61 -0
- package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/packages/primitives/dist/{chunk-PB3LFHXU.js → chunk-VUPWYBGU.js} +14 -0
- package/packages/primitives/dist/index.js +1 -1
- package/packages/primitives/dist/machines/range-slider.d.ts +3 -3
- package/packages/primitives/dist/machines/slider.d.ts +22 -0
- package/packages/primitives/dist/machines/slider.js +1 -1
- package/packages/primitives/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/packages/primitives/src/machines/slider.ts +17 -0
- package/packages/react/dist/index.d.ts +15 -1
- package/packages/react/dist/index.js +89 -21
- package/packages/react/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/packages/react/src/floating/FloatingPositioner.tsx +8 -0
- package/packages/react/src/hooks/use-anchor-position.ts +88 -17
- package/packages/react/src/menu/index.tsx +37 -3
- package/packages/react/src/popover/index.tsx +7 -1
- package/packages/react/src/slider/index.tsx +54 -14
- package/packages/react/src/tooltip/index.tsx +7 -1
- package/packages/schemas/prompts/cursorrules.md +3 -1
- package/packages/schemas/prompts/statecharts.md +1 -1
- package/packages/schemas/src/prompts.ts +3 -1
- package/scripts/link-scoped-packages.mjs +206 -0
- package/scripts/vite-aliases.mjs +6 -8
|
@@ -25,6 +25,8 @@ interface SliderContextValue {
|
|
|
25
25
|
dragging: boolean
|
|
26
26
|
send: ReturnType<typeof useAeonMachine<typeof sliderMachine>>[1]
|
|
27
27
|
onValueChange?: (value: number) => void
|
|
28
|
+
/** Snap, store and report a user-intended value. */
|
|
29
|
+
commit: (value: number) => void
|
|
28
30
|
setValueFromClientX: (clientX: number) => void
|
|
29
31
|
trackRef: React.RefObject<HTMLDivElement | null>
|
|
30
32
|
}
|
|
@@ -83,14 +85,33 @@ const Root = forwardRef<HTMLDivElement, SliderRootProps>(function SliderRoot(
|
|
|
83
85
|
const resolvedValue = value ?? snapshot.context.value
|
|
84
86
|
const dragging = snapshot.matches({ interaction: 'dragging' })
|
|
85
87
|
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
onValueChange?.(resolvedValue)
|
|
88
|
-
}, [resolvedValue, onValueChange])
|
|
89
|
-
|
|
90
88
|
useEffect(() => {
|
|
91
89
|
if (value !== undefined) send({ type: 'SET_VALUE', value })
|
|
92
90
|
}, [value, send])
|
|
93
91
|
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
send({ type: 'SET_BOUNDS', min, max, step })
|
|
94
|
+
}, [min, max, step, send])
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
send({ type: 'SET_DISABLED', disabled })
|
|
98
|
+
}, [disabled, send])
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Interaction is emitted here, never echoed from the resolved value. A
|
|
102
|
+
* controlled slider therefore reports what the user did (Aeon ≤1.4.0 stayed
|
|
103
|
+
* silent while `value` was set) and never fires on mount.
|
|
104
|
+
*/
|
|
105
|
+
const commit = useCallback(
|
|
106
|
+
(next: number) => {
|
|
107
|
+
if (disabled) return
|
|
108
|
+
const snapped = snapSliderValue(next, min, max, step)
|
|
109
|
+
send({ type: 'SET_VALUE', value: snapped })
|
|
110
|
+
onValueChange?.(snapped)
|
|
111
|
+
},
|
|
112
|
+
[disabled, min, max, step, send, onValueChange],
|
|
113
|
+
)
|
|
114
|
+
|
|
94
115
|
const setValueFromClientX = useCallback(
|
|
95
116
|
(clientX: number) => {
|
|
96
117
|
const track = trackRef.current
|
|
@@ -98,11 +119,9 @@ const Root = forwardRef<HTMLDivElement, SliderRootProps>(function SliderRoot(
|
|
|
98
119
|
const rect = track.getBoundingClientRect()
|
|
99
120
|
if (rect.width <= 0) return
|
|
100
121
|
const ratio = Math.min(1, Math.max(0, (clientX - rect.left) / rect.width))
|
|
101
|
-
|
|
102
|
-
send({ type: 'SET_VALUE', value: next })
|
|
103
|
-
if (value === undefined) onValueChange?.(next)
|
|
122
|
+
commit(min + ratio * (max - min))
|
|
104
123
|
},
|
|
105
|
-
[disabled, min, max
|
|
124
|
+
[commit, disabled, min, max],
|
|
106
125
|
)
|
|
107
126
|
|
|
108
127
|
useEffect(() => {
|
|
@@ -127,10 +146,22 @@ const Root = forwardRef<HTMLDivElement, SliderRootProps>(function SliderRoot(
|
|
|
127
146
|
dragging,
|
|
128
147
|
send,
|
|
129
148
|
onValueChange,
|
|
149
|
+
commit,
|
|
130
150
|
setValueFromClientX,
|
|
131
151
|
trackRef,
|
|
132
152
|
}),
|
|
133
|
-
[
|
|
153
|
+
[
|
|
154
|
+
resolvedValue,
|
|
155
|
+
min,
|
|
156
|
+
max,
|
|
157
|
+
step,
|
|
158
|
+
disabled,
|
|
159
|
+
dragging,
|
|
160
|
+
send,
|
|
161
|
+
onValueChange,
|
|
162
|
+
commit,
|
|
163
|
+
setValueFromClientX,
|
|
164
|
+
],
|
|
134
165
|
)
|
|
135
166
|
|
|
136
167
|
return (
|
|
@@ -201,7 +232,8 @@ const Thumb = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(funct
|
|
|
201
232
|
{ onKeyDown, onPointerDown, style, ...rest },
|
|
202
233
|
ref,
|
|
203
234
|
) {
|
|
204
|
-
const { value, min, max, step, disabled, dragging, send, setValueFromClientX } =
|
|
235
|
+
const { value, min, max, step, disabled, dragging, send, commit, setValueFromClientX } =
|
|
236
|
+
useSliderCtx()
|
|
205
237
|
|
|
206
238
|
return (
|
|
207
239
|
<span
|
|
@@ -229,19 +261,27 @@ const Thumb = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(funct
|
|
|
229
261
|
if (disabled || e.defaultPrevented) return
|
|
230
262
|
if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {
|
|
231
263
|
e.preventDefault()
|
|
232
|
-
|
|
264
|
+
commit(value + step)
|
|
233
265
|
}
|
|
234
266
|
if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {
|
|
235
267
|
e.preventDefault()
|
|
236
|
-
|
|
268
|
+
commit(value - step)
|
|
269
|
+
}
|
|
270
|
+
if (e.key === 'PageUp') {
|
|
271
|
+
e.preventDefault()
|
|
272
|
+
commit(value + (max - min) / 10)
|
|
273
|
+
}
|
|
274
|
+
if (e.key === 'PageDown') {
|
|
275
|
+
e.preventDefault()
|
|
276
|
+
commit(value - (max - min) / 10)
|
|
237
277
|
}
|
|
238
278
|
if (e.key === 'Home') {
|
|
239
279
|
e.preventDefault()
|
|
240
|
-
|
|
280
|
+
commit(min)
|
|
241
281
|
}
|
|
242
282
|
if (e.key === 'End') {
|
|
243
283
|
e.preventDefault()
|
|
244
|
-
|
|
284
|
+
commit(max)
|
|
245
285
|
}
|
|
246
286
|
},
|
|
247
287
|
},
|
|
@@ -272,11 +272,15 @@ export interface TooltipPositionerProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
272
272
|
/** Mount tooltip in document.body (default true). */
|
|
273
273
|
portalled?: boolean
|
|
274
274
|
placement?: AnchorPlacement
|
|
275
|
+
/** Gap between trigger and tip (default 4). */
|
|
276
|
+
gutter?: number
|
|
277
|
+
/** Stack level for the portalled surface (default 50). */
|
|
278
|
+
zIndex?: number
|
|
275
279
|
children?: ReactNode
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
const Positioner = forwardRef<HTMLDivElement, TooltipPositionerProps>(function TooltipPositioner(
|
|
279
|
-
{ portalled = true, placement = 'top-start', children, className, ...rest },
|
|
283
|
+
{ portalled = true, placement = 'top-start', gutter, zIndex, children, className, ...rest },
|
|
280
284
|
ref,
|
|
281
285
|
) {
|
|
282
286
|
const { open, triggerRef, positionerRef } = useTooltipCtx()
|
|
@@ -291,6 +295,8 @@ const Positioner = forwardRef<HTMLDivElement, TooltipPositionerProps>(function T
|
|
|
291
295
|
positionerRef={positionerRef}
|
|
292
296
|
portalled={portalled}
|
|
293
297
|
placement={placement}
|
|
298
|
+
gutter={gutter}
|
|
299
|
+
zIndex={zIndex}
|
|
294
300
|
className={className}
|
|
295
301
|
{...rest}
|
|
296
302
|
>
|
|
@@ -35,7 +35,9 @@ When generating Aeon UI, constrain props/parts/states to @aeon-ui/schemas catalo
|
|
|
35
35
|
Import headless from @aeon-ui/react or styled from @aeon-ui/ui.
|
|
36
36
|
Install: npm install aeon-ui-engine react react-dom xstate @xstate/react
|
|
37
37
|
CSS: import 'aeon-ui-engine/aeon.css'
|
|
38
|
-
|
|
38
|
+
Link: postinstall + npx aeon-ui link (node_modules/@aeon-ui/*)
|
|
39
|
+
Next.js: transpilePackages for @aeon-ui/* + "use client"; Vite plugin optional
|
|
40
|
+
Vue/Solid/Svelte: thin adapters only — React is the full catalog
|
|
39
41
|
|
|
40
42
|
## Async region statechart
|
|
41
43
|
States: idle → loading → (success | empty | failure); REFRESH from success/empty/failure; STALE flag while success.
|
|
@@ -34,7 +34,7 @@ Rule: Hidden input stays in sync with snapshot for forms.
|
|
|
34
34
|
|
|
35
35
|
## Slider statechart
|
|
36
36
|
Machine: sliderMachine — idle | dragging; value/min/max/step in context.
|
|
37
|
-
Events: SET_VALUE, STEP, POINTER_DOWN, POINTER_UP, HOME, END.
|
|
37
|
+
Events: SET_VALUE, STEP, POINTER_DOWN, POINTER_UP, HOME, END, SET_BOUNDS, SET_DISABLED.
|
|
38
38
|
Rule: Disabled blocks SET_VALUE / drag; project idle vs dragging on data-aeon-state.
|
|
39
39
|
|
|
40
40
|
## Content region statechart
|
|
@@ -128,7 +128,9 @@ When generating Aeon UI, constrain props/parts/states to @aeon-ui/schemas catalo
|
|
|
128
128
|
Import headless from @aeon-ui/react or styled from @aeon-ui/ui.
|
|
129
129
|
Install: npm install aeon-ui-engine react react-dom xstate @xstate/react
|
|
130
130
|
CSS: import 'aeon-ui-engine/aeon.css'
|
|
131
|
-
|
|
131
|
+
Link: postinstall + npx aeon-ui link (node_modules/@aeon-ui/*)
|
|
132
|
+
Next.js: transpilePackages for @aeon-ui/* + "use client"; Vite plugin optional
|
|
133
|
+
Vue/Solid/Svelte: thin adapters only — React is the full catalog
|
|
132
134
|
|
|
133
135
|
${STATECHART_PROMPTS.async}
|
|
134
136
|
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Materialize `node_modules/@aeon-ui/*` → `aeon-ui-engine/packages/*`
|
|
3
|
+
* so Next.js / Vite / Node can resolve scoped imports without bundler aliases.
|
|
4
|
+
*
|
|
5
|
+
* Runs as `aeon-ui-engine` postinstall (uses INIT_CWD) or via `npx aeon-ui link`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* node ./scripts/link-scoped-packages.mjs
|
|
9
|
+
* node ./scripts/link-scoped-packages.mjs --cwd /path/to/app
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createRequire } from 'node:module'
|
|
13
|
+
import {
|
|
14
|
+
existsSync,
|
|
15
|
+
lstatSync,
|
|
16
|
+
mkdirSync,
|
|
17
|
+
readlinkSync,
|
|
18
|
+
realpathSync,
|
|
19
|
+
rmSync,
|
|
20
|
+
symlinkSync,
|
|
21
|
+
} from 'node:fs'
|
|
22
|
+
import path from 'node:path'
|
|
23
|
+
import { fileURLToPath } from 'node:url'
|
|
24
|
+
|
|
25
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
|
|
26
|
+
|
|
27
|
+
/** Packages exposed under `@aeon-ui/<name>` for consumers. */
|
|
28
|
+
export const SCOPED_PACKAGES = [
|
|
29
|
+
'core',
|
|
30
|
+
'primitives',
|
|
31
|
+
'react',
|
|
32
|
+
'ui',
|
|
33
|
+
'panda',
|
|
34
|
+
'schemas',
|
|
35
|
+
'surface',
|
|
36
|
+
'vue',
|
|
37
|
+
'solid',
|
|
38
|
+
'svelte',
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Absolute path to the `aeon-ui-engine` package root (npm install or monorepo).
|
|
43
|
+
*/
|
|
44
|
+
export function resolveEngineRoot(opts = {}) {
|
|
45
|
+
if (opts.engineRoot) return path.resolve(opts.engineRoot)
|
|
46
|
+
if (process.env.AEON_UI_ROOT) return path.resolve(process.env.AEON_UI_ROOT)
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const require = createRequire(import.meta.url)
|
|
50
|
+
return path.dirname(require.resolve('aeon-ui-engine/package.json'))
|
|
51
|
+
} catch {
|
|
52
|
+
// Running from the monorepo checkout (this file lives in scripts/).
|
|
53
|
+
return path.resolve(scriptDir, '..')
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Consumer `node_modules` where `@aeon-ui/*` should appear.
|
|
59
|
+
* Prefer INIT_CWD (npm/pnpm/yarn set this to the install project).
|
|
60
|
+
*/
|
|
61
|
+
export function resolveTargetNodeModules(opts = {}) {
|
|
62
|
+
if (opts.nodeModules) return path.resolve(opts.nodeModules)
|
|
63
|
+
if (opts.cwd) return path.join(path.resolve(opts.cwd), 'node_modules')
|
|
64
|
+
|
|
65
|
+
// Prefer INIT_CWD (npm/pnpm/yarn set this to the install project).
|
|
66
|
+
// Skip when postinstall runs inside the engine package itself during a
|
|
67
|
+
// monorepo install — workspace already provides @aeon-ui/*.
|
|
68
|
+
if (process.env.INIT_CWD) {
|
|
69
|
+
const initCwd = path.resolve(process.env.INIT_CWD)
|
|
70
|
+
const engineRoot = resolveEngineRoot(opts)
|
|
71
|
+
if (initCwd === engineRoot) {
|
|
72
|
+
return path.join(engineRoot, 'node_modules')
|
|
73
|
+
}
|
|
74
|
+
return path.join(initCwd, 'node_modules')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const engineRoot = resolveEngineRoot(opts)
|
|
78
|
+
// Installed as dependency: …/node_modules/aeon-ui-engine
|
|
79
|
+
const parent = path.dirname(engineRoot)
|
|
80
|
+
if (path.basename(parent) === 'node_modules') {
|
|
81
|
+
return parent
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Monorepo / direct run: link into engine's own node_modules
|
|
85
|
+
return path.join(engineRoot, 'node_modules')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function isSymlink(p) {
|
|
89
|
+
try {
|
|
90
|
+
return lstatSync(p).isSymbolicLink()
|
|
91
|
+
} catch {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function sameTarget(linkPath, absTarget) {
|
|
97
|
+
try {
|
|
98
|
+
const current = readlinkSync(linkPath)
|
|
99
|
+
const resolved = path.isAbsolute(current)
|
|
100
|
+
? path.normalize(current)
|
|
101
|
+
: path.resolve(path.dirname(linkPath), current)
|
|
102
|
+
if (resolved === absTarget) return true
|
|
103
|
+
} catch {
|
|
104
|
+
/* not a symlink or unreadable */
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
return realpathSync(linkPath) === realpathSync(absTarget)
|
|
108
|
+
} catch {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {{ cwd?: string, engineRoot?: string, nodeModules?: string, quiet?: boolean, force?: boolean }} [opts]
|
|
115
|
+
* @returns {{ linked: string[], skipped: string[], missing: string[], targetNodeModules: string, engineRoot: string }}
|
|
116
|
+
*/
|
|
117
|
+
export function linkScopedPackages(opts = {}) {
|
|
118
|
+
const quiet = opts.quiet ?? false
|
|
119
|
+
const force = opts.force ?? false
|
|
120
|
+
const engineRoot = resolveEngineRoot(opts)
|
|
121
|
+
const targetNodeModules = resolveTargetNodeModules({ ...opts, engineRoot })
|
|
122
|
+
const scopeDir = path.join(targetNodeModules, '@aeon-ui')
|
|
123
|
+
const packagesRoot = path.join(engineRoot, 'packages')
|
|
124
|
+
|
|
125
|
+
const linked = []
|
|
126
|
+
const skipped = []
|
|
127
|
+
const missing = []
|
|
128
|
+
|
|
129
|
+
mkdirSync(scopeDir, { recursive: true })
|
|
130
|
+
|
|
131
|
+
for (const name of SCOPED_PACKAGES) {
|
|
132
|
+
const absTarget = path.join(packagesRoot, name)
|
|
133
|
+
if (!existsSync(absTarget)) {
|
|
134
|
+
missing.push(name)
|
|
135
|
+
continue
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const linkPath = path.join(scopeDir, name)
|
|
139
|
+
|
|
140
|
+
if (existsSync(linkPath) || isSymlink(linkPath)) {
|
|
141
|
+
if (sameTarget(linkPath, absTarget)) {
|
|
142
|
+
skipped.push(name)
|
|
143
|
+
continue
|
|
144
|
+
}
|
|
145
|
+
// Do not clobber pnpm/npm workspace links unless --force
|
|
146
|
+
if (!force) {
|
|
147
|
+
skipped.push(name)
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
rmSync(linkPath, { recursive: true, force: true })
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const type = process.platform === 'win32' ? 'junction' : 'dir'
|
|
154
|
+
symlinkSync(absTarget, linkPath, type)
|
|
155
|
+
linked.push(name)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!quiet) {
|
|
159
|
+
const rel = (n) => `@aeon-ui/${n}`
|
|
160
|
+
for (const n of linked) console.log(` link ${rel(n)} → packages/${n}`)
|
|
161
|
+
for (const n of skipped) console.log(` skip ${rel(n)} (already present)`)
|
|
162
|
+
for (const n of missing) console.log(` miss ${rel(n)} (not in engine)`)
|
|
163
|
+
if (linked.length === 0 && skipped.length > 0) {
|
|
164
|
+
console.log(`aeon-ui link: ${skipped.length} package(s) already present in ${targetNodeModules}`)
|
|
165
|
+
} else if (linked.length > 0) {
|
|
166
|
+
console.log(`aeon-ui link: linked ${linked.length} package(s) into ${targetNodeModules}`)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { linked, skipped, missing, targetNodeModules, engineRoot }
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function parseArgs(argv) {
|
|
174
|
+
const opts = {}
|
|
175
|
+
for (let i = 0; i < argv.length; i++) {
|
|
176
|
+
const a = argv[i]
|
|
177
|
+
if (a === '--cwd' && argv[i + 1]) {
|
|
178
|
+
opts.cwd = argv[++i]
|
|
179
|
+
} else if (a === '--engine-root' && argv[i + 1]) {
|
|
180
|
+
opts.engineRoot = argv[++i]
|
|
181
|
+
} else if (a === '--quiet' || a === '-q') {
|
|
182
|
+
opts.quiet = true
|
|
183
|
+
} else if (a === '--force' || a === '-f') {
|
|
184
|
+
opts.force = true
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return opts
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const isMain = (() => {
|
|
191
|
+
if (!process.argv[1]) return false
|
|
192
|
+
try {
|
|
193
|
+
return realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])
|
|
194
|
+
} catch {
|
|
195
|
+
return path.resolve(fileURLToPath(import.meta.url)) === path.resolve(process.argv[1])
|
|
196
|
+
}
|
|
197
|
+
})()
|
|
198
|
+
|
|
199
|
+
if (isMain) {
|
|
200
|
+
try {
|
|
201
|
+
linkScopedPackages(parseArgs(process.argv.slice(2)))
|
|
202
|
+
} catch (err) {
|
|
203
|
+
console.error('aeon-ui link failed:', err instanceof Error ? err.message : err)
|
|
204
|
+
process.exitCode = 1
|
|
205
|
+
}
|
|
206
|
+
}
|
package/scripts/vite-aliases.mjs
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Vite
|
|
2
|
+
* Vite helpers for apps that install `aeon-ui-engine` from npm.
|
|
3
|
+
*
|
|
4
|
+
* Scoped `@aeon-ui/*` imports resolve via postinstall linking
|
|
5
|
+
* (`aeon-ui-engine/link` / `npx aeon-ui link`). This plugin is optional —
|
|
6
|
+
* it still helps with optimizeDeps and monorepo `packagesRoot`.
|
|
3
7
|
*
|
|
4
8
|
* @example
|
|
5
|
-
* // vite.config.ts —
|
|
9
|
+
* // vite.config.ts — optional
|
|
6
10
|
* import { aeonUiVitePlugin } from 'aeon-ui-engine/vite'
|
|
7
11
|
*
|
|
8
12
|
* export default defineConfig({
|
|
9
13
|
* plugins: [react(), aeonUiVitePlugin()],
|
|
10
14
|
* })
|
|
11
|
-
*
|
|
12
|
-
* // tsconfig.json — spread the base config
|
|
13
|
-
* {
|
|
14
|
-
* "extends": "aeon-ui-engine/tsconfig",
|
|
15
|
-
* "compilerOptions": { "jsx": "react-jsx" }
|
|
16
|
-
* }
|
|
17
15
|
*/
|
|
18
16
|
import { createRequire } from 'node:module'
|
|
19
17
|
import path from 'node:path'
|