@adea-ai/ui 0.122.3 → 0.123.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/dist/components/layout/split-layout/resize-controller-core-retry.d.ts +13 -0
- package/dist/components/layout/split-layout/resize-controller-core-retry.d.ts.map +1 -0
- package/dist/components/layout/split-layout/resize-controller-core-retry.js +63 -0
- package/dist/components/layout/split-layout/resize-controller-core-retry.js.map +1 -0
- package/dist/components/layout/split-layout/resize-controller-core.d.ts +13 -0
- package/dist/components/layout/split-layout/resize-controller-core.d.ts.map +1 -0
- package/dist/components/layout/split-layout/resize-controller-core.js +63 -0
- package/dist/components/layout/split-layout/resize-controller-core.js.map +1 -0
- package/dist/components/layout/split-layout/resize-controller-retry-2.d.ts +3 -0
- package/dist/components/layout/split-layout/resize-controller-retry-2.d.ts.map +1 -0
- package/dist/components/layout/split-layout/resize-controller-retry-2.js +2 -0
- package/dist/components/layout/split-layout/resize-controller-retry.d.ts +2 -0
- package/dist/components/layout/split-layout/resize-controller-retry.d.ts.map +1 -0
- package/dist/components/layout/split-layout/resize-controller-retry.js +2 -0
- package/dist/components/layout/split-layout/resize-controller.d.ts +2 -0
- package/dist/components/layout/split-layout/resize-controller.d.ts.map +1 -0
- package/dist/components/layout/split-layout/resize-controller.js +2 -0
- package/dist/components/layout/split-layout/split-layout.d.ts.map +1 -1
- package/dist/components/layout/split-layout/split-layout.js +171 -60
- package/dist/components/layout/split-layout/split-layout.js.map +1 -1
- package/dist/lib/themes.d.ts +8 -7
- package/dist/lib/themes.d.ts.map +1 -1
- package/dist/lib/themes.js +53 -55
- package/dist/lib/themes.js.map +1 -1
- package/dist/r/appearance-editor.json +1 -1
- package/dist/r/lib.json +1 -1
- package/dist/r/registry.json +29 -3
- package/dist/r/split-layout.json +26 -0
- package/dist/r/src/components/layout/split-layout/resize-controller-core-retry.tsx +66 -0
- package/dist/r/src/components/layout/split-layout/resize-controller-core.tsx +66 -0
- package/dist/r/src/components/layout/split-layout/resize-controller-retry-2.tsx +2 -0
- package/dist/r/src/components/layout/split-layout/resize-controller-retry.tsx +1 -0
- package/dist/r/src/components/layout/split-layout/resize-controller.tsx +1 -0
- package/dist/r/src/components/layout/split-layout/split-layout.tsx +197 -49
- package/dist/r/src/lib/themes.ts +56 -73
- package/dist/r/theming.json +1 -1
- package/package.json +2 -2
- package/registry.json +29 -3
- package/src/components/layout/split-layout/resize-controller-core-retry.tsx +66 -0
- package/src/components/layout/split-layout/resize-controller-core.tsx +66 -0
- package/src/components/layout/split-layout/resize-controller-retry-2.tsx +2 -0
- package/src/components/layout/split-layout/resize-controller-retry.tsx +1 -0
- package/src/components/layout/split-layout/resize-controller.tsx +1 -0
- package/src/components/layout/split-layout/split-layout.tsx +197 -49
- package/src/lib/themes.ts +56 -73
package/dist/r/src/lib/themes.ts
CHANGED
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
*
|
|
25
25
|
* ## The mapping, and the entry that is not a rename
|
|
26
26
|
*
|
|
27
|
-
*
|
|
28
|
-
* entry will trip a reader: the catalogue's `accent`
|
|
29
|
-
* `primary`, because in the shadcn vocabulary `--primary` is
|
|
30
|
-
* fill of a primary button, the thing a focus ring is drawn
|
|
31
|
-
* a low-contrast hover wash. The catalogue's `accent` is
|
|
32
|
-
* `--primary`, and `--accent` is filled from
|
|
33
|
-
* components actually use it for.
|
|
27
|
+
* The package-owned `shadcnVariables` adapter maps canonical roles onto this
|
|
28
|
+
* system's vocabulary. One entry will trip a reader: the catalogue's `accent`
|
|
29
|
+
* becomes this system's `primary`, because in the shadcn vocabulary `--primary` is
|
|
30
|
+
* the action colour — the fill of a primary button, the thing a focus ring is drawn
|
|
31
|
+
* in — while `--accent` is a low-contrast hover wash. The catalogue's `accent` is
|
|
32
|
+
* the former, so it goes to `--primary`, and `--accent` is filled from
|
|
33
|
+
* `surfaceHover`, which is what shadcn components actually use it for.
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
import {
|
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
type AdeaThemeRecord,
|
|
57
57
|
type ContrastFinding,
|
|
58
58
|
} from '@adea-ai/themes'
|
|
59
|
+
import { shadcnVariables } from '@adea-ai/themes/adapters/shadcn'
|
|
59
60
|
import { isThemeAccentId } from './theme-accents'
|
|
60
61
|
|
|
61
62
|
export { isThemeAccentId } from './theme-accents'
|
|
@@ -106,6 +107,7 @@ export type ThemeColors = {
|
|
|
106
107
|
sidebarForeground: string
|
|
107
108
|
sidebarAccent: string
|
|
108
109
|
sidebarBorder: string
|
|
110
|
+
sidebarMutedForeground: string
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
/** The sixteen ANSI colours a terminal needs, plus its cursor and selection. */
|
|
@@ -179,75 +181,56 @@ export type ThemeVariant = {
|
|
|
179
181
|
provenance: ThemeProvenance
|
|
180
182
|
}
|
|
181
183
|
|
|
182
|
-
/**
|
|
183
|
-
* Canonical role → this system's `ThemeColors` key.
|
|
184
|
-
*
|
|
185
|
-
* Read by {@link toVariant}. The two derived destructive-action presentation values
|
|
186
|
-
* are intentionally excluded; the shared Themes adapter owns their color math.
|
|
187
|
-
*/
|
|
188
|
-
type ThemeRole = Exclude<keyof ThemeColors, 'destructiveAction' | 'destructiveActionForeground'>
|
|
189
|
-
|
|
190
|
-
const ROLE_FOR: Readonly<Record<ThemeRole, keyof AdeaThemeRecord['colors']>> = {
|
|
191
|
-
background: 'background',
|
|
192
|
-
foreground: 'text',
|
|
193
|
-
card: 'surface',
|
|
194
|
-
cardForeground: 'text',
|
|
195
|
-
popover: 'surfaceElevated',
|
|
196
|
-
popoverForeground: 'text',
|
|
197
|
-
// Not a rename — see this module's header.
|
|
198
|
-
primary: 'accent',
|
|
199
|
-
primaryForeground: 'accentForeground',
|
|
200
|
-
// shadcn's `secondary` and `muted` are both the first surface rung used as a fill.
|
|
201
|
-
secondary: 'surface',
|
|
202
|
-
secondaryForeground: 'text',
|
|
203
|
-
muted: 'surface',
|
|
204
|
-
mutedForeground: 'textMuted',
|
|
205
|
-
// shadcn's `accent` is a hover wash, which is exactly `surfaceHover`.
|
|
206
|
-
accent: 'surfaceHover',
|
|
207
|
-
accentForeground: 'text',
|
|
208
|
-
destructive: 'error',
|
|
209
|
-
// Overwritten below from the measured pairing; nominal here so the table is total.
|
|
210
|
-
destructiveForeground: 'error',
|
|
211
|
-
destructiveSubtle: 'error',
|
|
212
|
-
success: 'success',
|
|
213
|
-
successForeground: 'success',
|
|
214
|
-
successSubtle: 'success',
|
|
215
|
-
warning: 'warning',
|
|
216
|
-
warningForeground: 'warning',
|
|
217
|
-
warningSubtle: 'warning',
|
|
218
|
-
info: 'info',
|
|
219
|
-
infoForeground: 'info',
|
|
220
|
-
infoSubtle: 'info',
|
|
221
|
-
border: 'border',
|
|
222
|
-
input: 'border',
|
|
223
|
-
ring: 'accent',
|
|
224
|
-
sidebar: 'surface',
|
|
225
|
-
sidebarForeground: 'text',
|
|
226
|
-
sidebarAccent: 'surfaceHover',
|
|
227
|
-
sidebarBorder: 'border',
|
|
228
|
-
}
|
|
229
|
-
|
|
230
184
|
/** Builds the design system's view of one catalogue entry. */
|
|
231
185
|
function toVariant(theme: AdeaThemeRecord): ThemeVariant {
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
186
|
+
const projected = shadcnVariables(theme)
|
|
187
|
+
const token = (name: string): string => {
|
|
188
|
+
const value = projected[`--${name}`]
|
|
189
|
+
if (!value) throw new Error(`${theme.id} has no shared shadcn projection for --${name}`)
|
|
190
|
+
return value
|
|
235
191
|
}
|
|
236
|
-
// Keep the semantic foreground paired with the canonical error role. Filled
|
|
237
|
-
// destructive actions use the distinct projection below so their /90 hover state
|
|
238
|
-
// remains readable without changing icons, borders, or tinted status surfaces.
|
|
239
|
-
colors.destructiveForeground = statusForeground(theme, 'error')
|
|
240
|
-
colors.destructiveSubtle = tint(theme.colors.error, theme.colors.background)
|
|
241
192
|
const destructiveAction = shadcnDestructiveProjection(theme)
|
|
242
|
-
colors
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
193
|
+
const colors: ThemeColors = {
|
|
194
|
+
background: token('background'),
|
|
195
|
+
foreground: token('foreground'),
|
|
196
|
+
card: token('card'),
|
|
197
|
+
cardForeground: token('card-foreground'),
|
|
198
|
+
popover: token('popover'),
|
|
199
|
+
popoverForeground: token('popover-foreground'),
|
|
200
|
+
primary: token('primary'),
|
|
201
|
+
primaryForeground: token('primary-foreground'),
|
|
202
|
+
secondary: token('secondary'),
|
|
203
|
+
secondaryForeground: token('secondary-foreground'),
|
|
204
|
+
muted: token('muted'),
|
|
205
|
+
mutedForeground: token('muted-foreground'),
|
|
206
|
+
accent: token('accent'),
|
|
207
|
+
accentForeground: token('accent-foreground'),
|
|
208
|
+
// Preserve the UI's semantic error token. The Themes projection uses its
|
|
209
|
+
// contrast-safe solid-action fill for --destructive; UI keeps that fill in
|
|
210
|
+
// the separate destructiveAction pair below.
|
|
211
|
+
destructive: theme.colors.error,
|
|
212
|
+
destructiveForeground: statusForeground(theme, 'error'),
|
|
213
|
+
destructiveSubtle: tint(theme.colors.error, theme.colors.background),
|
|
214
|
+
destructiveAction: destructiveAction.fill,
|
|
215
|
+
destructiveActionForeground: destructiveAction.foreground,
|
|
216
|
+
success: token('success'),
|
|
217
|
+
successForeground: statusForeground(theme, 'success'),
|
|
218
|
+
successSubtle: tint(theme.colors.success, theme.colors.background),
|
|
219
|
+
warning: token('warning'),
|
|
220
|
+
warningForeground: statusForeground(theme, 'warning'),
|
|
221
|
+
warningSubtle: tint(theme.colors.warning, theme.colors.background),
|
|
222
|
+
info: token('info'),
|
|
223
|
+
infoForeground: statusForeground(theme, 'info'),
|
|
224
|
+
infoSubtle: tint(theme.colors.info, theme.colors.background),
|
|
225
|
+
border: token('border'),
|
|
226
|
+
input: token('input'),
|
|
227
|
+
ring: token('ring'),
|
|
228
|
+
sidebar: token('sidebar'),
|
|
229
|
+
sidebarForeground: token('sidebar-foreground'),
|
|
230
|
+
sidebarAccent: token('sidebar-accent'),
|
|
231
|
+
sidebarBorder: token('sidebar-border'),
|
|
232
|
+
sidebarMutedForeground: token('sidebar-muted-foreground'),
|
|
233
|
+
}
|
|
251
234
|
const syntax = syntaxRoles(theme)
|
|
252
235
|
|
|
253
236
|
return {
|
|
@@ -556,7 +539,7 @@ export function themeCssVariables(theme: ThemeVariant): Record<string, string> {
|
|
|
556
539
|
'--sidebar-primary': c.primary,
|
|
557
540
|
'--sidebar-primary-foreground': c.primaryForeground,
|
|
558
541
|
'--sidebar-ring': c.ring,
|
|
559
|
-
'--sidebar-muted-foreground': c.
|
|
542
|
+
'--sidebar-muted-foreground': c.sidebarMutedForeground,
|
|
560
543
|
'--surface-sunken': c.muted,
|
|
561
544
|
'--surface-hover': c.accent,
|
|
562
545
|
'--surface-active': c.border,
|
package/dist/r/theming.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adea-ai/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.123.1",
|
|
4
4
|
"description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adea",
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
"check:packed-paste-model": "node scripts/check-packed-paste-model.mjs"
|
|
130
130
|
},
|
|
131
131
|
"dependencies": {
|
|
132
|
-
"@adea-ai/themes": "^0.
|
|
132
|
+
"@adea-ai/themes": "^0.10.4",
|
|
133
133
|
"@corvu/calendar": "^0.1.2",
|
|
134
134
|
"@corvu/drawer": "^0.2.4",
|
|
135
135
|
"@corvu/otp-field": "^0.1.4",
|
package/registry.json
CHANGED
|
@@ -1811,6 +1811,7 @@
|
|
|
1811
1811
|
],
|
|
1812
1812
|
"registryDependencies": [
|
|
1813
1813
|
"@adea-ai/ui/action-button",
|
|
1814
|
+
"@adea-ai/ui/button",
|
|
1814
1815
|
"lib"
|
|
1815
1816
|
],
|
|
1816
1817
|
"files": [
|
|
@@ -1834,6 +1835,31 @@
|
|
|
1834
1835
|
"type": "registry:ui",
|
|
1835
1836
|
"target": "components/layout/split-layout/model.ts"
|
|
1836
1837
|
},
|
|
1838
|
+
{
|
|
1839
|
+
"path": "src/components/layout/split-layout/resize-controller-core-retry.tsx",
|
|
1840
|
+
"type": "registry:ui",
|
|
1841
|
+
"target": "components/layout/split-layout/resize-controller-core-retry.tsx"
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
"path": "src/components/layout/split-layout/resize-controller-core.tsx",
|
|
1845
|
+
"type": "registry:ui",
|
|
1846
|
+
"target": "components/layout/split-layout/resize-controller-core.tsx"
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
"path": "src/components/layout/split-layout/resize-controller-retry-2.tsx",
|
|
1850
|
+
"type": "registry:ui",
|
|
1851
|
+
"target": "components/layout/split-layout/resize-controller-retry-2.tsx"
|
|
1852
|
+
},
|
|
1853
|
+
{
|
|
1854
|
+
"path": "src/components/layout/split-layout/resize-controller-retry.tsx",
|
|
1855
|
+
"type": "registry:ui",
|
|
1856
|
+
"target": "components/layout/split-layout/resize-controller-retry.tsx"
|
|
1857
|
+
},
|
|
1858
|
+
{
|
|
1859
|
+
"path": "src/components/layout/split-layout/resize-controller.tsx",
|
|
1860
|
+
"type": "registry:ui",
|
|
1861
|
+
"target": "components/layout/split-layout/resize-controller.tsx"
|
|
1862
|
+
},
|
|
1837
1863
|
{
|
|
1838
1864
|
"path": "src/components/layout/split-layout/split-layout.tsx",
|
|
1839
1865
|
"type": "registry:ui",
|
|
@@ -1998,7 +2024,7 @@
|
|
|
1998
2024
|
"title": "Appearance Editor",
|
|
1999
2025
|
"description": "",
|
|
2000
2026
|
"dependencies": [
|
|
2001
|
-
"@adea-ai/themes@^0.
|
|
2027
|
+
"@adea-ai/themes@^0.10.4",
|
|
2002
2028
|
"@kobalte/core@^0.13.14",
|
|
2003
2029
|
"lucide-solid@^1.51.0"
|
|
2004
2030
|
],
|
|
@@ -2477,7 +2503,7 @@
|
|
|
2477
2503
|
"title": "Theming",
|
|
2478
2504
|
"description": "",
|
|
2479
2505
|
"dependencies": [
|
|
2480
|
-
"@adea-ai/themes@^0.
|
|
2506
|
+
"@adea-ai/themes@^0.10.4",
|
|
2481
2507
|
"@kobalte/core@^0.13.14",
|
|
2482
2508
|
"lucide-solid@^1.51.0"
|
|
2483
2509
|
],
|
|
@@ -2592,7 +2618,7 @@
|
|
|
2592
2618
|
"title": "Class-name and token helpers",
|
|
2593
2619
|
"description": "The private helpers the components import: the class-name merge, the variant recipes, the token manifest and the theme bridge. Installed automatically as a peer of any component that needs it.",
|
|
2594
2620
|
"dependencies": [
|
|
2595
|
-
"@adea-ai/themes@^0.
|
|
2621
|
+
"@adea-ai/themes@^0.10.4",
|
|
2596
2622
|
"class-variance-authority@^0.7.1",
|
|
2597
2623
|
"cn@^0.4.0"
|
|
2598
2624
|
],
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import Resizable from '@corvu/resizable'
|
|
2
|
+
import { type Accessor, type JSX } from 'solid-js'
|
|
3
|
+
import {
|
|
4
|
+
listLeaves,
|
|
5
|
+
MIN_SPLIT_RATIO,
|
|
6
|
+
MAX_SPLIT_RATIO,
|
|
7
|
+
type SplitLayoutBranch,
|
|
8
|
+
type SplitLayoutLeaf,
|
|
9
|
+
} from './model'
|
|
10
|
+
|
|
11
|
+
export type SplitLayoutResizeControllerProps<L extends SplitLayoutLeaf> = {
|
|
12
|
+
branch: Accessor<SplitLayoutBranch<L>>
|
|
13
|
+
rect: Accessor<JSX.CSSProperties>
|
|
14
|
+
domId: (id: string) => string
|
|
15
|
+
root: () => HTMLDivElement | undefined
|
|
16
|
+
labelForSeparator?: (branch: SplitLayoutBranch<L>) => string
|
|
17
|
+
onResize: (splitId: string, ratio: number) => void
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Corvu stays behind the first real split while the pane owners remain mounted. */
|
|
21
|
+
export default function SplitLayoutResizeController<L extends SplitLayoutLeaf>(
|
|
22
|
+
props: SplitLayoutResizeControllerProps<L>
|
|
23
|
+
) {
|
|
24
|
+
const id = () => props.branch().id
|
|
25
|
+
return (
|
|
26
|
+
<Resizable
|
|
27
|
+
orientation={props.branch().direction === 'row' ? 'horizontal' : 'vertical'}
|
|
28
|
+
sizes={[props.branch().ratio, 1 - props.branch().ratio]}
|
|
29
|
+
keyboardDelta={0.05}
|
|
30
|
+
onSizesChange={(sizes) => {
|
|
31
|
+
// Corvu also reports panel registration/unregistration while
|
|
32
|
+
// mounting or disposing a controller. Those incomplete or
|
|
33
|
+
// hidden-host sizes are not user resize intent.
|
|
34
|
+
const root = props.root()
|
|
35
|
+
if (!root?.isConnected || root.getClientRects().length === 0) return
|
|
36
|
+
if (
|
|
37
|
+
sizes.length !== 2 ||
|
|
38
|
+
sizes.some((size) => !Number.isFinite(size)) ||
|
|
39
|
+
Math.abs(sizes[0]! + sizes[1]! - 1) > 0.000001
|
|
40
|
+
)
|
|
41
|
+
return
|
|
42
|
+
if (sizes[0] !== undefined && Math.abs(sizes[0] - props.branch().ratio) > 0.000001)
|
|
43
|
+
props.onResize(id(), sizes[0])
|
|
44
|
+
}}
|
|
45
|
+
style={props.rect()}
|
|
46
|
+
class="pointer-events-none absolute flex min-h-0 min-w-0 data-[orientation=vertical]:flex-col"
|
|
47
|
+
>
|
|
48
|
+
<Resizable.Panel minSize={MIN_SPLIT_RATIO} maxSize={MAX_SPLIT_RATIO} aria-hidden="true" />
|
|
49
|
+
<Resizable.Handle
|
|
50
|
+
aria-label={
|
|
51
|
+
props.labelForSeparator?.(props.branch()) ??
|
|
52
|
+
(props.branch().direction === 'row' ? 'Resize pane columns' : 'Resize pane rows')
|
|
53
|
+
}
|
|
54
|
+
aria-orientation={props.branch().direction === 'row' ? 'vertical' : 'horizontal'}
|
|
55
|
+
aria-controls={listLeaves(props.branch())
|
|
56
|
+
.map((leaf) => props.domId(leaf.id))
|
|
57
|
+
.join(' ')}
|
|
58
|
+
aria-valuemin={10}
|
|
59
|
+
aria-valuemax={90}
|
|
60
|
+
aria-valuenow={Math.round(props.branch().ratio * 100)}
|
|
61
|
+
class="pointer-events-auto relative w-px shrink-0 bg-border after:absolute after:inset-y-0 after:-inset-x-1 after:w-3 focus-visible:bg-primary focus-visible:outline-none hover:bg-primary data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-1 data-[orientation=vertical]:after:h-3 data-[orientation=vertical]:after:w-full"
|
|
62
|
+
/>
|
|
63
|
+
<Resizable.Panel minSize={MIN_SPLIT_RATIO} maxSize={MAX_SPLIT_RATIO} aria-hidden="true" />
|
|
64
|
+
</Resizable>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import Resizable from '@corvu/resizable'
|
|
2
|
+
import { type Accessor, type JSX } from 'solid-js'
|
|
3
|
+
import {
|
|
4
|
+
listLeaves,
|
|
5
|
+
MIN_SPLIT_RATIO,
|
|
6
|
+
MAX_SPLIT_RATIO,
|
|
7
|
+
type SplitLayoutBranch,
|
|
8
|
+
type SplitLayoutLeaf,
|
|
9
|
+
} from './model'
|
|
10
|
+
|
|
11
|
+
export type SplitLayoutResizeControllerProps<L extends SplitLayoutLeaf> = {
|
|
12
|
+
branch: Accessor<SplitLayoutBranch<L>>
|
|
13
|
+
rect: Accessor<JSX.CSSProperties>
|
|
14
|
+
domId: (id: string) => string
|
|
15
|
+
root: () => HTMLDivElement | undefined
|
|
16
|
+
labelForSeparator?: (branch: SplitLayoutBranch<L>) => string
|
|
17
|
+
onResize: (splitId: string, ratio: number) => void
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Corvu stays behind the first real split while the pane owners remain mounted. */
|
|
21
|
+
export default function SplitLayoutResizeController<L extends SplitLayoutLeaf>(
|
|
22
|
+
props: SplitLayoutResizeControllerProps<L>
|
|
23
|
+
) {
|
|
24
|
+
const id = () => props.branch().id
|
|
25
|
+
return (
|
|
26
|
+
<Resizable
|
|
27
|
+
orientation={props.branch().direction === 'row' ? 'horizontal' : 'vertical'}
|
|
28
|
+
sizes={[props.branch().ratio, 1 - props.branch().ratio]}
|
|
29
|
+
keyboardDelta={0.05}
|
|
30
|
+
onSizesChange={(sizes) => {
|
|
31
|
+
// Corvu also reports panel registration/unregistration while
|
|
32
|
+
// mounting or disposing a controller. Those incomplete or
|
|
33
|
+
// hidden-host sizes are not user resize intent.
|
|
34
|
+
const root = props.root()
|
|
35
|
+
if (!root?.isConnected || root.getClientRects().length === 0) return
|
|
36
|
+
if (
|
|
37
|
+
sizes.length !== 2 ||
|
|
38
|
+
sizes.some((size) => !Number.isFinite(size)) ||
|
|
39
|
+
Math.abs(sizes[0]! + sizes[1]! - 1) > 0.000001
|
|
40
|
+
)
|
|
41
|
+
return
|
|
42
|
+
if (sizes[0] !== undefined && Math.abs(sizes[0] - props.branch().ratio) > 0.000001)
|
|
43
|
+
props.onResize(id(), sizes[0])
|
|
44
|
+
}}
|
|
45
|
+
style={props.rect()}
|
|
46
|
+
class="pointer-events-none absolute flex min-h-0 min-w-0 data-[orientation=vertical]:flex-col"
|
|
47
|
+
>
|
|
48
|
+
<Resizable.Panel minSize={MIN_SPLIT_RATIO} maxSize={MAX_SPLIT_RATIO} aria-hidden="true" />
|
|
49
|
+
<Resizable.Handle
|
|
50
|
+
aria-label={
|
|
51
|
+
props.labelForSeparator?.(props.branch()) ??
|
|
52
|
+
(props.branch().direction === 'row' ? 'Resize pane columns' : 'Resize pane rows')
|
|
53
|
+
}
|
|
54
|
+
aria-orientation={props.branch().direction === 'row' ? 'vertical' : 'horizontal'}
|
|
55
|
+
aria-controls={listLeaves(props.branch())
|
|
56
|
+
.map((leaf) => props.domId(leaf.id))
|
|
57
|
+
.join(' ')}
|
|
58
|
+
aria-valuemin={10}
|
|
59
|
+
aria-valuemax={90}
|
|
60
|
+
aria-valuenow={Math.round(props.branch().ratio * 100)}
|
|
61
|
+
class="pointer-events-auto relative w-px shrink-0 bg-border after:absolute after:inset-y-0 after:-inset-x-1 after:w-3 focus-visible:bg-primary focus-visible:outline-none hover:bg-primary data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-1 data-[orientation=vertical]:after:h-3 data-[orientation=vertical]:after:w-full"
|
|
62
|
+
/>
|
|
63
|
+
<Resizable.Panel minSize={MIN_SPLIT_RATIO} maxSize={MAX_SPLIT_RATIO} aria-hidden="true" />
|
|
64
|
+
</Resizable>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './resize-controller-core'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './resize-controller-core'
|