@nixxie-cms/core 2.0.0 → 2.2.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.
- package/admin-ui/components/dist/nixxie-cms-core-admin-ui-components.cjs.js +7 -7
- package/admin-ui/components/dist/nixxie-cms-core-admin-ui-components.esm.js +7 -7
- package/admin-ui/context/dist/nixxie-cms-core-admin-ui-context.cjs.js +2 -2
- package/admin-ui/context/dist/nixxie-cms-core-admin-ui-context.esm.js +2 -2
- package/admin-ui/utils/dist/nixxie-cms-core-admin-ui-utils.cjs.js +5 -5
- package/admin-ui/utils/dist/nixxie-cms-core-admin-ui-utils.esm.js +3 -3
- package/dist/{CreateItemDialog-7008b050.esm.js → CreateItemDialog-66621fe8.esm.js} +3 -3
- package/dist/{CreateItemDialog-a0cab315.cjs.js → CreateItemDialog-96b044ce.cjs.js} +4 -4
- package/dist/{Field-47f85161.esm.js → Field-1820c4e6.esm.js} +1 -0
- package/dist/{Field-ed8d7627.cjs.js → Field-38d3cdf9.cjs.js} +1 -0
- package/dist/GraphQLErrorNotice-7594a9f8.esm.js +64 -0
- package/dist/GraphQLErrorNotice-c8890f80.cjs.js +66 -0
- package/dist/{PageContainer-5ae731cc.esm.js → PageContainer-355cfbfa.esm.js} +362 -156
- package/dist/{PageContainer-abd7159f.cjs.js → PageContainer-4095555a.cjs.js} +361 -155
- package/dist/{context-af9957ed.esm.js → context-2924eaaa.esm.js} +53 -58
- package/dist/{context-b5204629.cjs.js → context-2ce61d0b.cjs.js} +53 -58
- package/dist/declarations/src/admin-ui/components/GraphQLErrorNotice.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/components/Navigation.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/components/PageContainer.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/context.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/bigInt/views/index.d.ts +2 -1
- package/dist/declarations/src/fields/types/bigInt/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/bytes/views/index.d.ts +2 -1
- package/dist/declarations/src/fields/types/bytes/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/calendarDay/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/decimal/views/index.d.ts +2 -1
- package/dist/declarations/src/fields/types/decimal/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/float/views/index.d.ts +2 -1
- package/dist/declarations/src/fields/types/float/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/integer/views/index.d.ts +2 -1
- package/dist/declarations/src/fields/types/integer/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/json/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/multiselect/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/select/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/text/views/index.d.ts +2 -1
- package/dist/declarations/src/fields/types/text/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/timestamp/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/virtual/views/index.d.ts.map +1 -1
- package/dist/declarations/src/internal-unstable/admin-ui/pages/HomePage/index.d.ts.map +1 -1
- package/dist/declarations/src/internal-unstable/admin-ui/pages/ItemPage/index.d.ts.map +1 -1
- package/dist/pick-4c785a54.esm.js +34 -0
- package/dist/pick-906341bb.cjs.js +37 -0
- package/dist/{useCreateItem-1f94d252.esm.js → useCreateItem-36a75f1c.esm.js} +26 -26
- package/dist/{useCreateItem-1be4987e.cjs.js → useCreateItem-acf06f77.cjs.js} +37 -37
- package/dist/{useFilter-acc9d413.cjs.js → useFilter-c29f17a8.cjs.js} +1 -1
- package/dist/{useFilter-9b6db1f9.esm.js → useFilter-f79b2abb.esm.js} +1 -1
- package/dist/{Fields-956d9a14.esm.js → usePreventNavigation-093389dd.esm.js} +28 -2
- package/dist/{Fields-e2c28056.cjs.js → usePreventNavigation-d4f9f4fa.cjs.js} +27 -0
- package/fields/types/bigInt/views/dist/nixxie-cms-core-fields-types-bigInt-views.cjs.js +8 -0
- package/fields/types/bigInt/views/dist/nixxie-cms-core-fields-types-bigInt-views.esm.js +8 -1
- package/fields/types/bytes/views/dist/nixxie-cms-core-fields-types-bytes-views.cjs.js +14 -3
- package/fields/types/bytes/views/dist/nixxie-cms-core-fields-types-bytes-views.esm.js +15 -5
- package/fields/types/calendarDay/views/dist/nixxie-cms-core-fields-types-calendarDay-views.cjs.js +2 -1
- package/fields/types/calendarDay/views/dist/nixxie-cms-core-fields-types-calendarDay-views.esm.js +2 -1
- package/fields/types/decimal/views/dist/nixxie-cms-core-fields-types-decimal-views.cjs.js +10 -1
- package/fields/types/decimal/views/dist/nixxie-cms-core-fields-types-decimal-views.esm.js +10 -2
- package/fields/types/file/views/dist/nixxie-cms-core-fields-types-file-views.cjs.js +1 -1
- package/fields/types/file/views/dist/nixxie-cms-core-fields-types-file-views.esm.js +2 -2
- package/fields/types/float/views/dist/nixxie-cms-core-fields-types-float-views.cjs.js +10 -1
- package/fields/types/float/views/dist/nixxie-cms-core-fields-types-float-views.esm.js +10 -2
- package/fields/types/image/views/dist/nixxie-cms-core-fields-types-image-views.cjs.js +2 -1
- package/fields/types/image/views/dist/nixxie-cms-core-fields-types-image-views.esm.js +2 -1
- package/fields/types/integer/views/dist/nixxie-cms-core-fields-types-integer-views.cjs.js +8 -0
- package/fields/types/integer/views/dist/nixxie-cms-core-fields-types-integer-views.esm.js +8 -1
- package/fields/types/json/views/dist/nixxie-cms-core-fields-types-json-views.cjs.js +19 -4
- package/fields/types/json/views/dist/nixxie-cms-core-fields-types-json-views.esm.js +19 -4
- package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.cjs.js +18 -3
- package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.esm.js +18 -3
- package/fields/types/password/views/dist/nixxie-cms-core-fields-types-password-views.cjs.js +1 -1
- package/fields/types/password/views/dist/nixxie-cms-core-fields-types-password-views.esm.js +1 -1
- package/fields/types/relationship/views/dist/nixxie-cms-core-fields-types-relationship-views.cjs.js +9 -7
- package/fields/types/relationship/views/dist/nixxie-cms-core-fields-types-relationship-views.esm.js +9 -7
- package/fields/types/select/views/dist/nixxie-cms-core-fields-types-select-views.cjs.js +3 -2
- package/fields/types/select/views/dist/nixxie-cms-core-fields-types-select-views.esm.js +3 -2
- package/fields/types/text/views/dist/nixxie-cms-core-fields-types-text-views.cjs.js +14 -3
- package/fields/types/text/views/dist/nixxie-cms-core-fields-types-text-views.esm.js +15 -5
- package/fields/types/timestamp/views/dist/nixxie-cms-core-fields-types-timestamp-views.cjs.js +2 -1
- package/fields/types/timestamp/views/dist/nixxie-cms-core-fields-types-timestamp-views.esm.js +2 -1
- package/fields/types/virtual/views/dist/nixxie-cms-core-fields-types-virtual-views.cjs.js +13 -1
- package/fields/types/virtual/views/dist/nixxie-cms-core-fields-types-virtual-views.esm.js +14 -2
- package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.cjs.js +3 -3
- package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.esm.js +3 -3
- package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.cjs.js +7 -7
- package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.esm.js +6 -6
- package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.cjs.js +34 -33
- package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.esm.js +35 -34
- package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.cjs.js +53 -13
- package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.esm.js +52 -12
- package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.cjs.js +36 -25
- package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.esm.js +36 -25
- package/package.json +2 -2
- package/src/admin-ui/components/CommandPalette.tsx +134 -27
- package/src/admin-ui/components/CreateButtonLink.tsx +20 -46
- package/src/admin-ui/components/GraphQLErrorNotice.tsx +39 -33
- package/src/admin-ui/components/Logo.tsx +5 -5
- package/src/admin-ui/components/Navigation.tsx +41 -27
- package/src/admin-ui/components/PageContainer.tsx +171 -15
- package/src/admin-ui/components/WelcomeDialog.tsx +14 -14
- package/src/admin-ui/context.tsx +5 -2
- package/src/admin-ui/utils/useCreateItem.ts +21 -1
- package/src/fields/types/bigInt/views/index.tsx +10 -1
- package/src/fields/types/bytes/views/index.tsx +14 -1
- package/src/fields/types/calendarDay/views/index.tsx +2 -1
- package/src/fields/types/decimal/views/index.tsx +7 -1
- package/src/fields/types/file/views/Field.tsx +1 -1
- package/src/fields/types/float/views/index.tsx +7 -1
- package/src/fields/types/image/views/index.tsx +1 -1
- package/src/fields/types/integer/views/index.tsx +5 -0
- package/src/fields/types/json/views/index.tsx +20 -2
- package/src/fields/types/multiselect/views/index.tsx +7 -3
- package/src/fields/types/password/views/index.tsx +1 -1
- package/src/fields/types/relationship/views/index.tsx +1 -0
- package/src/fields/types/select/views/index.tsx +2 -1
- package/src/fields/types/text/views/index.tsx +14 -1
- package/src/fields/types/timestamp/views/__tests__/index.tsx +68 -68
- package/src/fields/types/timestamp/views/index.tsx +2 -1
- package/src/fields/types/virtual/views/index.tsx +17 -2
- package/src/internal-unstable/admin-ui/pages/HomePage/index.tsx +40 -31
- package/src/internal-unstable/admin-ui/pages/ItemPage/index.tsx +36 -3
- package/src/internal-unstable/admin-ui/pages/ListPage/PaginationControls.tsx +20 -33
- package/src/internal-unstable/admin-ui/pages/ListPage/index.tsx +24 -16
- package/tests/conditional-filters.test.ts +333 -326
- package/dist/GraphQLErrorNotice-cd74180d.cjs.js +0 -57
- package/dist/GraphQLErrorNotice-d9f0931b.esm.js +0 -55
- package/dist/pick-5fe45878.cjs.js +0 -71
- package/dist/pick-b7ef3115.esm.js +0 -68
|
@@ -4,9 +4,10 @@ var NextHead = require('next/head');
|
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var style = require('@keystar/ui/style');
|
|
6
6
|
var NextLink = require('next/link');
|
|
7
|
-
var adminUi_context_dist_nixxieCmsCoreAdminUiContext = require('./context-
|
|
7
|
+
var adminUi_context_dist_nixxieCmsCoreAdminUiContext = require('./context-2ce61d0b.cjs.js');
|
|
8
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
9
|
var router = require('next/router');
|
|
10
|
+
var utils = require('@react-aria/utils');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
12
13
|
|
|
@@ -32,7 +33,7 @@ function DefaultLogo() {
|
|
|
32
33
|
outline: 0,
|
|
33
34
|
flexShrink: 0,
|
|
34
35
|
'&:focus-visible': {
|
|
35
|
-
outline:
|
|
36
|
+
outline: `2px solid ${style.tokenSchema.color.scale.black}`,
|
|
36
37
|
outlineOffset: 3,
|
|
37
38
|
borderRadius: 4
|
|
38
39
|
}
|
|
@@ -45,7 +46,7 @@ function DefaultLogo() {
|
|
|
45
46
|
width: 28,
|
|
46
47
|
height: 28,
|
|
47
48
|
borderRadius: 6,
|
|
48
|
-
backgroundColor:
|
|
49
|
+
backgroundColor: style.tokenSchema.color.scale.black,
|
|
49
50
|
flexShrink: 0
|
|
50
51
|
}),
|
|
51
52
|
children: /*#__PURE__*/jsxRuntime.jsx("svg", {
|
|
@@ -55,7 +56,7 @@ function DefaultLogo() {
|
|
|
55
56
|
fill: "none",
|
|
56
57
|
children: /*#__PURE__*/jsxRuntime.jsx("path", {
|
|
57
58
|
d: "M2.5 11V3L11.5 11V3",
|
|
58
|
-
stroke:
|
|
59
|
+
stroke: style.tokenSchema.color.scale.white,
|
|
59
60
|
strokeWidth: "1.8",
|
|
60
61
|
strokeLinecap: "round",
|
|
61
62
|
strokeLinejoin: "round"
|
|
@@ -66,7 +67,7 @@ function DefaultLogo() {
|
|
|
66
67
|
fontSize: 14,
|
|
67
68
|
fontWeight: 600,
|
|
68
69
|
letterSpacing: '-0.03em',
|
|
69
|
-
color:
|
|
70
|
+
color: style.tokenSchema.color.foreground.neutralEmphasis,
|
|
70
71
|
lineHeight: 1,
|
|
71
72
|
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif"
|
|
72
73
|
}),
|
|
@@ -90,8 +91,10 @@ function NavItem({
|
|
|
90
91
|
indent
|
|
91
92
|
}) {
|
|
92
93
|
const router$1 = router.useRouter();
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
// Active on an exact match, or when the current route is nested under `href`
|
|
95
|
+
// (prefix match on a path boundary). Dashboard ('/') is only active on an
|
|
96
|
+
// exact match so it doesn't light up for every nested route.
|
|
97
|
+
const isActive = router$1.pathname === href || href !== '/' && router$1.pathname.startsWith(href + '/');
|
|
95
98
|
return /*#__PURE__*/jsxRuntime.jsxs("a", {
|
|
96
99
|
href: href,
|
|
97
100
|
onClick: e => {
|
|
@@ -108,8 +111,8 @@ function NavItem({
|
|
|
108
111
|
paddingBlock: '7px',
|
|
109
112
|
fontSize: 13,
|
|
110
113
|
fontWeight: isActive ? 500 : 400,
|
|
111
|
-
color: isActive ?
|
|
112
|
-
backgroundColor: isActive ?
|
|
114
|
+
color: isActive ? style.tokenSchema.color.foreground.neutralEmphasis : style.tokenSchema.color.foreground.neutralSecondary,
|
|
115
|
+
backgroundColor: isActive ? style.tokenSchema.color.background.surfaceSecondary : 'transparent',
|
|
113
116
|
textDecoration: 'none',
|
|
114
117
|
borderRadius: '0 6px 6px 0',
|
|
115
118
|
marginRight: '12px',
|
|
@@ -118,8 +121,8 @@ function NavItem({
|
|
|
118
121
|
userSelect: 'none',
|
|
119
122
|
transition: 'color 120ms, background-color 120ms',
|
|
120
123
|
'&:hover': {
|
|
121
|
-
color:
|
|
122
|
-
backgroundColor:
|
|
124
|
+
color: style.tokenSchema.color.foreground.neutralEmphasis,
|
|
125
|
+
backgroundColor: style.tokenSchema.color.background.surfaceSecondary
|
|
123
126
|
}
|
|
124
127
|
}),
|
|
125
128
|
children: [isActive && /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
@@ -130,7 +133,7 @@ function NavItem({
|
|
|
130
133
|
bottom: '20%',
|
|
131
134
|
width: 2,
|
|
132
135
|
borderRadius: '0 2px 2px 0',
|
|
133
|
-
backgroundColor:
|
|
136
|
+
backgroundColor: style.tokenSchema.color.scale.black
|
|
134
137
|
})
|
|
135
138
|
}), /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
136
139
|
className: style.css({
|
|
@@ -165,7 +168,7 @@ function SectionLabel({
|
|
|
165
168
|
fontWeight: 600,
|
|
166
169
|
letterSpacing: '0.10em',
|
|
167
170
|
textTransform: 'uppercase',
|
|
168
|
-
color:
|
|
171
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
169
172
|
}),
|
|
170
173
|
children: children
|
|
171
174
|
}), action]
|
|
@@ -182,7 +185,7 @@ function NavDivider() {
|
|
|
182
185
|
height: 1,
|
|
183
186
|
marginInline: '16px',
|
|
184
187
|
marginBlock: '6px',
|
|
185
|
-
backgroundColor:
|
|
188
|
+
backgroundColor: style.tokenSchema.color.border.muted
|
|
186
189
|
})
|
|
187
190
|
});
|
|
188
191
|
}
|
|
@@ -206,20 +209,20 @@ function SearchTrigger({
|
|
|
206
209
|
paddingInline: '10px',
|
|
207
210
|
paddingBlock: '7px',
|
|
208
211
|
borderRadius: 6,
|
|
209
|
-
border:
|
|
210
|
-
backgroundColor:
|
|
211
|
-
color:
|
|
212
|
+
border: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
213
|
+
backgroundColor: style.tokenSchema.color.background.surfaceSecondary,
|
|
214
|
+
color: style.tokenSchema.color.foreground.neutralSecondary,
|
|
212
215
|
fontSize: 12.5,
|
|
213
216
|
cursor: 'pointer',
|
|
214
217
|
textAlign: 'left',
|
|
215
218
|
transition: 'border-color 140ms, background 140ms, color 140ms',
|
|
216
219
|
'&:hover': {
|
|
217
|
-
borderColor:
|
|
218
|
-
backgroundColor:
|
|
219
|
-
color:
|
|
220
|
+
borderColor: style.tokenSchema.color.border.emphasis,
|
|
221
|
+
backgroundColor: style.tokenSchema.color.background.surfaceSecondary,
|
|
222
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
220
223
|
},
|
|
221
224
|
'&:focus-visible': {
|
|
222
|
-
outline:
|
|
225
|
+
outline: `2px solid ${style.tokenSchema.color.scale.black}`,
|
|
223
226
|
outlineOffset: 2
|
|
224
227
|
}
|
|
225
228
|
}),
|
|
@@ -251,7 +254,7 @@ function SearchTrigger({
|
|
|
251
254
|
}), /*#__PURE__*/jsxRuntime.jsx("kbd", {
|
|
252
255
|
className: style.css({
|
|
253
256
|
fontSize: 10.5,
|
|
254
|
-
color:
|
|
257
|
+
color: style.tokenSchema.color.foreground.neutralSecondary,
|
|
255
258
|
fontFamily: 'inherit',
|
|
256
259
|
letterSpacing: '0.02em'
|
|
257
260
|
}),
|
|
@@ -283,18 +286,18 @@ function NavSearch({
|
|
|
283
286
|
paddingInline: '10px',
|
|
284
287
|
paddingBlock: '5px',
|
|
285
288
|
fontSize: 12.5,
|
|
286
|
-
border:
|
|
289
|
+
border: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
287
290
|
borderRadius: 5,
|
|
288
|
-
backgroundColor:
|
|
289
|
-
color:
|
|
291
|
+
backgroundColor: style.tokenSchema.color.background.surfaceSecondary,
|
|
292
|
+
color: style.tokenSchema.color.foreground.neutralEmphasis,
|
|
290
293
|
outline: 'none',
|
|
291
294
|
boxSizing: 'border-box',
|
|
292
295
|
transition: 'border-color 140ms',
|
|
293
296
|
'&:focus': {
|
|
294
|
-
borderColor:
|
|
297
|
+
borderColor: style.tokenSchema.color.alias.borderHovered
|
|
295
298
|
},
|
|
296
299
|
'&::placeholder': {
|
|
297
|
-
color:
|
|
300
|
+
color: style.tokenSchema.color.foreground.neutralTertiary
|
|
298
301
|
},
|
|
299
302
|
'&::-webkit-search-cancel-button': {
|
|
300
303
|
display: 'none'
|
|
@@ -328,7 +331,7 @@ function CollectionsSection({
|
|
|
328
331
|
className: style.css({
|
|
329
332
|
margin: '4px 16px',
|
|
330
333
|
fontSize: 12.5,
|
|
331
|
-
color:
|
|
334
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
332
335
|
}),
|
|
333
336
|
children: "No results"
|
|
334
337
|
}) : filtered.map(list => /*#__PURE__*/jsxRuntime.jsxs(NavItem, {
|
|
@@ -339,7 +342,7 @@ function CollectionsSection({
|
|
|
339
342
|
marginLeft: 6,
|
|
340
343
|
fontSize: 10,
|
|
341
344
|
fontWeight: 500,
|
|
342
|
-
color:
|
|
345
|
+
color: style.tokenSchema.color.foreground.neutralSecondary,
|
|
343
346
|
letterSpacing: '0.04em',
|
|
344
347
|
textTransform: 'uppercase'
|
|
345
348
|
}),
|
|
@@ -401,7 +404,7 @@ function Navigation({
|
|
|
401
404
|
className: style.css({
|
|
402
405
|
margin: '8px 16px',
|
|
403
406
|
fontSize: 12.5,
|
|
404
|
-
color:
|
|
407
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
405
408
|
}),
|
|
406
409
|
children: "No collections"
|
|
407
410
|
}), process.env.NODE_ENV !== 'production' && apiPath && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
@@ -448,7 +451,7 @@ function NavFooter({
|
|
|
448
451
|
className: style.css({
|
|
449
452
|
paddingInline: '12px',
|
|
450
453
|
paddingBlock: '10px',
|
|
451
|
-
borderTop:
|
|
454
|
+
borderTop: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
452
455
|
marginTop: 'auto'
|
|
453
456
|
}),
|
|
454
457
|
children: children
|
|
@@ -505,6 +508,8 @@ function CommandPalette({
|
|
|
505
508
|
const [activeIndex, setActiveIndex] = react.useState(0);
|
|
506
509
|
const inputRef = react.useRef(null);
|
|
507
510
|
const listRef = react.useRef(null);
|
|
511
|
+
const panelRef = react.useRef(null);
|
|
512
|
+
const listboxId = utils.useId();
|
|
508
513
|
const commands = useCommands();
|
|
509
514
|
const filtered = react.useMemo(() => {
|
|
510
515
|
if (!query.trim()) return commands;
|
|
@@ -532,11 +537,29 @@ function CommandPalette({
|
|
|
532
537
|
if (!isOpen) return;
|
|
533
538
|
setQuery('');
|
|
534
539
|
setActiveIndex(0);
|
|
540
|
+
|
|
541
|
+
// FOCUS RESTORE: remember what was focused before the palette opened.
|
|
542
|
+
const previouslyFocused = document.activeElement;
|
|
543
|
+
|
|
544
|
+
// SCROLL LOCK: prevent the page behind the modal from scrolling.
|
|
545
|
+
const prevOverflow = document.body.style.overflow;
|
|
546
|
+
document.body.style.overflow = 'hidden';
|
|
535
547
|
const t = setTimeout(() => {
|
|
536
548
|
var _inputRef$current;
|
|
537
549
|
return (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
|
|
538
550
|
}, 10);
|
|
539
|
-
return () =>
|
|
551
|
+
return () => {
|
|
552
|
+
clearTimeout(t);
|
|
553
|
+
// Restore scroll position behaviour.
|
|
554
|
+
document.body.style.overflow = prevOverflow;
|
|
555
|
+
// Restore focus to whatever held it before we opened.
|
|
556
|
+
try {
|
|
557
|
+
var _previouslyFocused$fo;
|
|
558
|
+
previouslyFocused === null || previouslyFocused === void 0 || (_previouslyFocused$fo = previouslyFocused.focus) === null || _previouslyFocused$fo === void 0 || _previouslyFocused$fo.call(previouslyFocused);
|
|
559
|
+
} catch {
|
|
560
|
+
/* element may be gone from the DOM — ignore */
|
|
561
|
+
}
|
|
562
|
+
};
|
|
540
563
|
}, [isOpen]);
|
|
541
564
|
react.useEffect(() => {
|
|
542
565
|
setActiveIndex(0);
|
|
@@ -558,6 +581,41 @@ function CommandPalette({
|
|
|
558
581
|
cmd.action();
|
|
559
582
|
}
|
|
560
583
|
}
|
|
584
|
+
|
|
585
|
+
// FOCUS TRAP + panel-level ESCAPE. Runs for any child of the panel so the
|
|
586
|
+
// modal closes regardless of which element currently holds focus, and Tab /
|
|
587
|
+
// Shift+Tab stay contained within the panel's focusable descendants.
|
|
588
|
+
function onPanelKeyDown(e) {
|
|
589
|
+
if (e.key === 'Escape') {
|
|
590
|
+
e.preventDefault();
|
|
591
|
+
onClose();
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
if (e.key !== 'Tab') return;
|
|
595
|
+
const panel = panelRef.current;
|
|
596
|
+
if (!panel) return;
|
|
597
|
+
let focusables;
|
|
598
|
+
try {
|
|
599
|
+
focusables = Array.from(panel.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter(el => el.offsetParent !== null || el === document.activeElement);
|
|
600
|
+
} catch {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
if (focusables.length === 0) return;
|
|
604
|
+
const first = focusables[0];
|
|
605
|
+
const last = focusables[focusables.length - 1];
|
|
606
|
+
const current = document.activeElement;
|
|
607
|
+
if (e.shiftKey) {
|
|
608
|
+
if (current === first || !panel.contains(current)) {
|
|
609
|
+
e.preventDefault();
|
|
610
|
+
last.focus();
|
|
611
|
+
}
|
|
612
|
+
} else {
|
|
613
|
+
if (current === last || !panel.contains(current)) {
|
|
614
|
+
e.preventDefault();
|
|
615
|
+
first.focus();
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
561
619
|
function onKeyDown(e) {
|
|
562
620
|
if (e.key === 'ArrowDown') {
|
|
563
621
|
e.preventDefault();
|
|
@@ -581,6 +639,12 @@ function CommandPalette({
|
|
|
581
639
|
flatList.forEach((cmd, i) => map.set(cmd.id, i));
|
|
582
640
|
return map;
|
|
583
641
|
}, [flatList]);
|
|
642
|
+
|
|
643
|
+
// Stable per-option id derived from the listbox id, used for both the rendered
|
|
644
|
+
// <li role="option"> ids and the input's aria-activedescendant.
|
|
645
|
+
const optionId = cmdId => `${listboxId}-opt-${cmdId}`;
|
|
646
|
+
const activeCommand = flatList[activeIndex];
|
|
647
|
+
const activeOptionId = activeCommand ? optionId(activeCommand.id) : undefined;
|
|
584
648
|
if (!isOpen) return null;
|
|
585
649
|
return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
586
650
|
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -588,14 +652,16 @@ function CommandPalette({
|
|
|
588
652
|
className: style.css({
|
|
589
653
|
position: 'fixed',
|
|
590
654
|
inset: 0,
|
|
591
|
-
backgroundColor:
|
|
655
|
+
backgroundColor: style.tokenSchema.color.alias.blanket,
|
|
592
656
|
zIndex: 200,
|
|
593
657
|
backdropFilter: 'blur(3px)'
|
|
594
658
|
})
|
|
595
659
|
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
660
|
+
ref: panelRef,
|
|
596
661
|
role: "dialog",
|
|
597
662
|
"aria-modal": "true",
|
|
598
663
|
"aria-label": "Command palette",
|
|
664
|
+
onKeyDown: onPanelKeyDown,
|
|
599
665
|
className: style.css({
|
|
600
666
|
position: 'fixed',
|
|
601
667
|
top: '14vh',
|
|
@@ -606,7 +672,7 @@ function CommandPalette({
|
|
|
606
672
|
maxHeight: '62vh',
|
|
607
673
|
display: 'flex',
|
|
608
674
|
flexDirection: 'column',
|
|
609
|
-
backgroundColor:
|
|
675
|
+
backgroundColor: style.tokenSchema.color.background.canvas,
|
|
610
676
|
borderRadius: 10,
|
|
611
677
|
boxShadow: '0 24px 64px rgba(0,0,0,0.22), 0 0 0 1px rgba(0,0,0,0.07)',
|
|
612
678
|
zIndex: 201,
|
|
@@ -618,16 +684,17 @@ function CommandPalette({
|
|
|
618
684
|
alignItems: 'center',
|
|
619
685
|
gap: 10,
|
|
620
686
|
padding: '12px 16px',
|
|
621
|
-
borderBottom:
|
|
687
|
+
borderBottom: `1px solid ${style.tokenSchema.color.border.muted}`
|
|
622
688
|
}),
|
|
623
689
|
children: [/*#__PURE__*/jsxRuntime.jsxs("svg", {
|
|
624
690
|
width: "15",
|
|
625
691
|
height: "15",
|
|
626
692
|
viewBox: "0 0 15 15",
|
|
627
693
|
fill: "none",
|
|
694
|
+
"aria-hidden": "true",
|
|
628
695
|
style: {
|
|
629
696
|
flexShrink: 0,
|
|
630
|
-
color:
|
|
697
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
631
698
|
},
|
|
632
699
|
children: [/*#__PURE__*/jsxRuntime.jsx("circle", {
|
|
633
700
|
cx: "6.5",
|
|
@@ -650,16 +717,22 @@ function CommandPalette({
|
|
|
650
717
|
onChange: e => setQuery(e.target.value),
|
|
651
718
|
onKeyDown: onKeyDown,
|
|
652
719
|
placeholder: "Search commands, lists, actions\u2026",
|
|
720
|
+
role: "combobox",
|
|
721
|
+
"aria-label": "Search commands",
|
|
722
|
+
"aria-expanded": flatList.length > 0,
|
|
723
|
+
"aria-controls": listboxId,
|
|
724
|
+
"aria-autocomplete": "list",
|
|
725
|
+
"aria-activedescendant": activeOptionId,
|
|
653
726
|
className: style.css({
|
|
654
727
|
flex: 1,
|
|
655
728
|
border: 'none',
|
|
656
729
|
outline: 'none',
|
|
657
730
|
fontSize: 14.5,
|
|
658
|
-
color:
|
|
731
|
+
color: style.tokenSchema.color.foreground.neutralEmphasis,
|
|
659
732
|
background: 'transparent',
|
|
660
733
|
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
|
|
661
734
|
'&::placeholder': {
|
|
662
|
-
color:
|
|
735
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
663
736
|
}
|
|
664
737
|
})
|
|
665
738
|
}), /*#__PURE__*/jsxRuntime.jsx("kbd", {
|
|
@@ -668,11 +741,11 @@ function CommandPalette({
|
|
|
668
741
|
alignItems: 'center',
|
|
669
742
|
gap: 2,
|
|
670
743
|
padding: '2px 7px',
|
|
671
|
-
backgroundColor:
|
|
672
|
-
border:
|
|
744
|
+
backgroundColor: style.tokenSchema.color.background.surfaceSecondary,
|
|
745
|
+
border: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
673
746
|
borderRadius: 5,
|
|
674
747
|
fontSize: 11,
|
|
675
|
-
color:
|
|
748
|
+
color: style.tokenSchema.color.foreground.neutralSecondary,
|
|
676
749
|
fontFamily: 'inherit',
|
|
677
750
|
flexShrink: 0
|
|
678
751
|
}),
|
|
@@ -680,7 +753,9 @@ function CommandPalette({
|
|
|
680
753
|
})]
|
|
681
754
|
}), /*#__PURE__*/jsxRuntime.jsx("ul", {
|
|
682
755
|
ref: listRef,
|
|
756
|
+
id: listboxId,
|
|
683
757
|
role: "listbox",
|
|
758
|
+
"aria-label": "Commands",
|
|
684
759
|
className: style.css({
|
|
685
760
|
flex: 1,
|
|
686
761
|
overflowY: 'auto',
|
|
@@ -691,7 +766,7 @@ function CommandPalette({
|
|
|
691
766
|
width: 4
|
|
692
767
|
},
|
|
693
768
|
'&::-webkit-scrollbar-thumb': {
|
|
694
|
-
background:
|
|
769
|
+
background: style.tokenSchema.color.border.muted,
|
|
695
770
|
borderRadius: 4
|
|
696
771
|
}
|
|
697
772
|
}),
|
|
@@ -699,124 +774,131 @@ function CommandPalette({
|
|
|
699
774
|
className: style.css({
|
|
700
775
|
padding: '28px 16px',
|
|
701
776
|
textAlign: 'center',
|
|
702
|
-
color:
|
|
777
|
+
color: style.tokenSchema.color.foreground.neutralSecondary,
|
|
703
778
|
fontSize: 13.5
|
|
704
779
|
}),
|
|
705
780
|
children: ["No results for \u201C", query, "\u201D"]
|
|
706
|
-
}) : Array.from(grouped.entries()).map(([category, items]) =>
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
backgroundColor: isActive ? '#0a0a0a' : 'transparent',
|
|
743
|
-
transition: 'background 100ms',
|
|
744
|
-
'&:hover': {
|
|
745
|
-
backgroundColor: isActive ? '#0a0a0a' : '#f5f5f5'
|
|
746
|
-
}
|
|
747
|
-
}),
|
|
748
|
-
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
781
|
+
}) : Array.from(grouped.entries()).map(([category, items], groupIdx) => {
|
|
782
|
+
const headerId = `${listboxId}-cat-${groupIdx}`;
|
|
783
|
+
return /*#__PURE__*/jsxRuntime.jsxs("li", {
|
|
784
|
+
role: "presentation",
|
|
785
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("p", {
|
|
786
|
+
id: headerId,
|
|
787
|
+
role: "presentation",
|
|
788
|
+
className: style.css({
|
|
789
|
+
margin: 0,
|
|
790
|
+
padding: '8px 16px 3px',
|
|
791
|
+
fontSize: 10,
|
|
792
|
+
fontWeight: 600,
|
|
793
|
+
letterSpacing: '0.10em',
|
|
794
|
+
textTransform: 'uppercase',
|
|
795
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
796
|
+
}),
|
|
797
|
+
children: category
|
|
798
|
+
}), /*#__PURE__*/jsxRuntime.jsx("ul", {
|
|
799
|
+
role: "group",
|
|
800
|
+
"aria-labelledby": headerId,
|
|
801
|
+
className: style.css({
|
|
802
|
+
listStyle: 'none',
|
|
803
|
+
margin: 0,
|
|
804
|
+
padding: 0
|
|
805
|
+
}),
|
|
806
|
+
children: items.map(cmd => {
|
|
807
|
+
var _cmdFlatIndex$get;
|
|
808
|
+
const idx = (_cmdFlatIndex$get = cmdFlatIndex.get(cmd.id)) !== null && _cmdFlatIndex$get !== void 0 ? _cmdFlatIndex$get : 0;
|
|
809
|
+
const isActive = idx === activeIndex;
|
|
810
|
+
return /*#__PURE__*/jsxRuntime.jsxs("li", {
|
|
811
|
+
id: optionId(cmd.id),
|
|
812
|
+
role: "option",
|
|
813
|
+
"aria-selected": isActive,
|
|
814
|
+
"data-active": isActive,
|
|
815
|
+
onClick: () => runCommand(cmd),
|
|
816
|
+
onMouseEnter: () => setActiveIndex(idx),
|
|
749
817
|
className: style.css({
|
|
750
|
-
display: '
|
|
818
|
+
display: 'flex',
|
|
751
819
|
alignItems: 'center',
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
flexShrink: 0,
|
|
761
|
-
transition: 'background 100ms, color 100ms',
|
|
762
|
-
fontFamily: 'monospace'
|
|
763
|
-
}),
|
|
764
|
-
children: cmd.icon
|
|
765
|
-
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
766
|
-
className: style.css({
|
|
767
|
-
flex: 1,
|
|
768
|
-
minWidth: 0
|
|
820
|
+
gap: 10,
|
|
821
|
+
padding: '7px 16px',
|
|
822
|
+
cursor: 'pointer',
|
|
823
|
+
backgroundColor: isActive ? style.tokenSchema.color.scale.black : 'transparent',
|
|
824
|
+
transition: 'background 100ms',
|
|
825
|
+
'&:hover': {
|
|
826
|
+
backgroundColor: isActive ? style.tokenSchema.color.scale.black : style.tokenSchema.color.background.surfaceSecondary
|
|
827
|
+
}
|
|
769
828
|
}),
|
|
770
829
|
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
771
830
|
className: style.css({
|
|
772
|
-
display: '
|
|
773
|
-
|
|
831
|
+
display: 'inline-flex',
|
|
832
|
+
alignItems: 'center',
|
|
833
|
+
justifyContent: 'center',
|
|
834
|
+
width: 28,
|
|
835
|
+
height: 28,
|
|
836
|
+
borderRadius: 6,
|
|
837
|
+
backgroundColor: isActive ? '#2a2a2a' : style.tokenSchema.color.background.surfaceSecondary,
|
|
838
|
+
fontSize: 12,
|
|
774
839
|
fontWeight: 500,
|
|
775
|
-
color: isActive ?
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
transition: 'color 100ms'
|
|
840
|
+
color: isActive ? style.tokenSchema.color.foreground.onEmphasis : style.tokenSchema.color.foreground.neutralSecondary,
|
|
841
|
+
flexShrink: 0,
|
|
842
|
+
transition: 'background 100ms, color 100ms',
|
|
843
|
+
fontFamily: 'monospace'
|
|
780
844
|
}),
|
|
781
|
-
children: cmd.
|
|
782
|
-
}),
|
|
845
|
+
children: cmd.icon
|
|
846
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
783
847
|
className: style.css({
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
848
|
+
flex: 1,
|
|
849
|
+
minWidth: 0
|
|
850
|
+
}),
|
|
851
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
852
|
+
className: style.css({
|
|
853
|
+
display: 'block',
|
|
854
|
+
fontSize: 13.5,
|
|
855
|
+
fontWeight: 500,
|
|
856
|
+
color: isActive ? style.tokenSchema.color.foreground.onEmphasis : style.tokenSchema.color.foreground.neutralEmphasis,
|
|
857
|
+
whiteSpace: 'nowrap',
|
|
858
|
+
overflow: 'hidden',
|
|
859
|
+
textOverflow: 'ellipsis',
|
|
860
|
+
transition: 'color 100ms'
|
|
861
|
+
}),
|
|
862
|
+
children: cmd.label
|
|
863
|
+
}), cmd.description && /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
864
|
+
className: style.css({
|
|
865
|
+
display: 'block',
|
|
866
|
+
fontSize: 12,
|
|
867
|
+
color: isActive ? style.tokenSchema.color.foreground.inverseSecondary : style.tokenSchema.color.foreground.neutralSecondary,
|
|
868
|
+
whiteSpace: 'nowrap',
|
|
869
|
+
overflow: 'hidden',
|
|
870
|
+
textOverflow: 'ellipsis',
|
|
871
|
+
transition: 'color 100ms'
|
|
872
|
+
}),
|
|
873
|
+
children: cmd.description
|
|
874
|
+
})]
|
|
875
|
+
}), isActive && /*#__PURE__*/jsxRuntime.jsx("kbd", {
|
|
876
|
+
className: style.css({
|
|
877
|
+
fontSize: 11,
|
|
878
|
+
color: style.tokenSchema.color.foreground.inverseSecondary,
|
|
879
|
+
background: '#2a2a2a',
|
|
880
|
+
border: '1px solid #3a3a3a',
|
|
881
|
+
borderRadius: 4,
|
|
882
|
+
padding: '2px 6px',
|
|
883
|
+
fontFamily: 'inherit',
|
|
884
|
+
flexShrink: 0
|
|
791
885
|
}),
|
|
792
|
-
children:
|
|
886
|
+
children: "\u21B5"
|
|
793
887
|
})]
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
border: '1px solid #3a3a3a',
|
|
800
|
-
borderRadius: 4,
|
|
801
|
-
padding: '2px 6px',
|
|
802
|
-
fontFamily: 'inherit',
|
|
803
|
-
flexShrink: 0
|
|
804
|
-
}),
|
|
805
|
-
children: "\u21B5"
|
|
806
|
-
})]
|
|
807
|
-
}, cmd.id);
|
|
808
|
-
})
|
|
809
|
-
})]
|
|
810
|
-
}, category))
|
|
888
|
+
}, cmd.id);
|
|
889
|
+
})
|
|
890
|
+
})]
|
|
891
|
+
}, category);
|
|
892
|
+
})
|
|
811
893
|
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
812
894
|
className: style.css({
|
|
813
895
|
display: 'flex',
|
|
814
896
|
alignItems: 'center',
|
|
815
897
|
gap: 14,
|
|
816
898
|
padding: '8px 16px',
|
|
817
|
-
borderTop:
|
|
899
|
+
borderTop: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
818
900
|
fontSize: 11,
|
|
819
|
-
color:
|
|
901
|
+
color: style.tokenSchema.color.foreground.neutralSecondary
|
|
820
902
|
}),
|
|
821
903
|
children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
822
904
|
children: [/*#__PURE__*/jsxRuntime.jsx("kbd", {
|
|
@@ -863,13 +945,54 @@ function PageWrapper(props) {
|
|
|
863
945
|
display: 'flex',
|
|
864
946
|
height: '100vh',
|
|
865
947
|
overflow: 'hidden',
|
|
866
|
-
backgroundColor:
|
|
948
|
+
backgroundColor: style.tokenSchema.color.background.surface,
|
|
867
949
|
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
|
|
868
950
|
}),
|
|
869
951
|
...props
|
|
870
952
|
});
|
|
871
953
|
}
|
|
872
954
|
|
|
955
|
+
// ---- Skip to content (WCAG 2.4.1 Bypass Blocks) ----
|
|
956
|
+
function SkipLink() {
|
|
957
|
+
return /*#__PURE__*/jsxRuntime.jsx("a", {
|
|
958
|
+
href: "#main-content",
|
|
959
|
+
className: style.css({
|
|
960
|
+
// Visually hidden, off-screen by default — kept out of the layout for mouse users.
|
|
961
|
+
position: 'absolute',
|
|
962
|
+
top: 0,
|
|
963
|
+
left: 0,
|
|
964
|
+
width: 1,
|
|
965
|
+
height: 1,
|
|
966
|
+
padding: 0,
|
|
967
|
+
margin: -1,
|
|
968
|
+
overflow: 'hidden',
|
|
969
|
+
clip: 'rect(0 0 0 0)',
|
|
970
|
+
whiteSpace: 'nowrap',
|
|
971
|
+
border: 0,
|
|
972
|
+
zIndex: 60,
|
|
973
|
+
// Reveal on keyboard focus.
|
|
974
|
+
'&:focus, &:focus-visible': {
|
|
975
|
+
width: 'auto',
|
|
976
|
+
height: 'auto',
|
|
977
|
+
padding: '10px 16px',
|
|
978
|
+
margin: 8,
|
|
979
|
+
clip: 'auto',
|
|
980
|
+
overflow: 'visible',
|
|
981
|
+
backgroundColor: style.tokenSchema.color.background.canvas,
|
|
982
|
+
color: style.tokenSchema.color.foreground.neutralEmphasis,
|
|
983
|
+
borderRadius: 6,
|
|
984
|
+
boxShadow: `0 2px 8px ${style.tokenSchema.color.shadow.regular}`,
|
|
985
|
+
outline: `2px solid ${style.tokenSchema.color.foreground.neutralEmphasis}`,
|
|
986
|
+
outlineOffset: 2,
|
|
987
|
+
textDecoration: 'none',
|
|
988
|
+
fontSize: 14,
|
|
989
|
+
fontWeight: 500
|
|
990
|
+
}
|
|
991
|
+
}),
|
|
992
|
+
children: "Skip to content"
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
|
|
873
996
|
// ---- Mobile overlay ----
|
|
874
997
|
function Backdrop({
|
|
875
998
|
isVisible,
|
|
@@ -881,7 +1004,7 @@ function Backdrop({
|
|
|
881
1004
|
className: style.css({
|
|
882
1005
|
position: 'fixed',
|
|
883
1006
|
inset: 0,
|
|
884
|
-
backgroundColor:
|
|
1007
|
+
backgroundColor: style.tokenSchema.color.alias.blanket,
|
|
885
1008
|
zIndex: 40,
|
|
886
1009
|
transition: 'opacity 200ms',
|
|
887
1010
|
opacity: isVisible ? 1 : 0,
|
|
@@ -895,16 +1018,91 @@ function Backdrop({
|
|
|
895
1018
|
}
|
|
896
1019
|
|
|
897
1020
|
// ---- Sidebar — pure white, precise ----
|
|
1021
|
+
const FOCUSABLE_SELECTOR = 'a[href],button:not([disabled]),input:not([disabled]),[tabindex]:not([tabindex="-1"])';
|
|
898
1022
|
function Sidebar({
|
|
899
1023
|
isOpen,
|
|
900
1024
|
onClose,
|
|
901
1025
|
onCmdK
|
|
902
1026
|
}) {
|
|
1027
|
+
const asideRef = react.useRef(null);
|
|
1028
|
+
// Element to restore focus to (the hamburger) once the drawer closes.
|
|
1029
|
+
const lastFocusedRef = react.useRef(null);
|
|
1030
|
+
|
|
1031
|
+
// Mobile drawer a11y: focus trap, Escape-to-close, initial focus, and focus
|
|
1032
|
+
// restore. `isOpen` is only ever true on mobile (the resize handler forces it
|
|
1033
|
+
// false at >=768px), so gating on it doubles as a mobile gate.
|
|
1034
|
+
react.useEffect(() => {
|
|
1035
|
+
if (!isOpen) return;
|
|
1036
|
+
const aside = asideRef.current;
|
|
1037
|
+
if (!aside) return;
|
|
1038
|
+
|
|
1039
|
+
// Save the currently focused element so we can restore it on close.
|
|
1040
|
+
try {
|
|
1041
|
+
const active = document.activeElement;
|
|
1042
|
+
lastFocusedRef.current = active instanceof HTMLElement ? active : null;
|
|
1043
|
+
} catch {
|
|
1044
|
+
lastFocusedRef.current = null;
|
|
1045
|
+
}
|
|
1046
|
+
const getFocusable = () => {
|
|
1047
|
+
try {
|
|
1048
|
+
return Array.from(aside.querySelectorAll(FOCUSABLE_SELECTOR)).filter(el => el.offsetParent !== null || el === document.activeElement);
|
|
1049
|
+
} catch {
|
|
1050
|
+
return [];
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
|
|
1054
|
+
// Move initial focus into the drawer.
|
|
1055
|
+
try {
|
|
1056
|
+
var _getFocusable$;
|
|
1057
|
+
(_getFocusable$ = getFocusable()[0]) === null || _getFocusable$ === void 0 || _getFocusable$.focus();
|
|
1058
|
+
} catch {
|
|
1059
|
+
/* noop */
|
|
1060
|
+
}
|
|
1061
|
+
function onKeyDown(e) {
|
|
1062
|
+
if (e.key === 'Escape') {
|
|
1063
|
+
e.preventDefault();
|
|
1064
|
+
onClose();
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
if (e.key !== 'Tab') return;
|
|
1068
|
+
const focusable = getFocusable();
|
|
1069
|
+
if (focusable.length === 0) {
|
|
1070
|
+
// Nothing focusable inside — keep focus from escaping anyway.
|
|
1071
|
+
e.preventDefault();
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
const first = focusable[0];
|
|
1075
|
+
const last = focusable[focusable.length - 1];
|
|
1076
|
+
const current = document.activeElement;
|
|
1077
|
+
if (e.shiftKey) {
|
|
1078
|
+
if (current === first || !(aside !== null && aside !== void 0 && aside.contains(current))) {
|
|
1079
|
+
e.preventDefault();
|
|
1080
|
+
last.focus();
|
|
1081
|
+
}
|
|
1082
|
+
} else if (current === last || !(aside !== null && aside !== void 0 && aside.contains(current))) {
|
|
1083
|
+
e.preventDefault();
|
|
1084
|
+
first.focus();
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
document.addEventListener('keydown', onKeyDown, true);
|
|
1088
|
+
return () => {
|
|
1089
|
+
document.removeEventListener('keydown', onKeyDown, true);
|
|
1090
|
+
// Restore focus to the trigger that opened the drawer.
|
|
1091
|
+
try {
|
|
1092
|
+
var _lastFocusedRef$curre;
|
|
1093
|
+
(_lastFocusedRef$curre = lastFocusedRef.current) === null || _lastFocusedRef$curre === void 0 || _lastFocusedRef$curre.focus();
|
|
1094
|
+
} catch {
|
|
1095
|
+
/* noop */
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
}, [isOpen, onClose]);
|
|
903
1099
|
return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
904
1100
|
children: [/*#__PURE__*/jsxRuntime.jsx(Backdrop, {
|
|
905
1101
|
isVisible: isOpen,
|
|
906
1102
|
onClick: onClose
|
|
907
1103
|
}), /*#__PURE__*/jsxRuntime.jsxs("aside", {
|
|
1104
|
+
id: "nixxie-sidebar",
|
|
1105
|
+
ref: asideRef,
|
|
908
1106
|
className: style.css({
|
|
909
1107
|
position: 'fixed',
|
|
910
1108
|
top: 0,
|
|
@@ -914,13 +1112,18 @@ function Sidebar({
|
|
|
914
1112
|
zIndex: 50,
|
|
915
1113
|
display: 'flex',
|
|
916
1114
|
flexDirection: 'column',
|
|
917
|
-
backgroundColor:
|
|
918
|
-
borderRight:
|
|
1115
|
+
backgroundColor: style.tokenSchema.color.background.canvas,
|
|
1116
|
+
borderRight: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
919
1117
|
transform: isOpen ? 'translateX(0)' : `translateX(-${SIDEBAR_WIDTH}px)`,
|
|
1118
|
+
// Closed off-canvas drawer must leave the tab order / AT tree on
|
|
1119
|
+
// mobile; `visibility:hidden` removes its descendants from both.
|
|
1120
|
+
visibility: isOpen ? 'visible' : 'hidden',
|
|
920
1121
|
transition: 'transform 220ms cubic-bezier(0.4,0,0.2,1)',
|
|
921
1122
|
'@media (min-width: 768px)': {
|
|
922
1123
|
position: 'relative',
|
|
923
1124
|
transform: 'translateX(0)',
|
|
1125
|
+
// Persistent desktop rail is always reachable.
|
|
1126
|
+
visibility: 'visible',
|
|
924
1127
|
flexShrink: 0
|
|
925
1128
|
}
|
|
926
1129
|
}),
|
|
@@ -930,7 +1133,7 @@ function Sidebar({
|
|
|
930
1133
|
alignItems: 'center',
|
|
931
1134
|
height: TOPBAR_HEIGHT,
|
|
932
1135
|
paddingInline: '16px',
|
|
933
|
-
borderBottom:
|
|
1136
|
+
borderBottom: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
934
1137
|
flexShrink: 0
|
|
935
1138
|
}),
|
|
936
1139
|
children: /*#__PURE__*/jsxRuntime.jsx(Logo, {})
|
|
@@ -944,7 +1147,7 @@ function Sidebar({
|
|
|
944
1147
|
width: 3
|
|
945
1148
|
},
|
|
946
1149
|
'&::-webkit-scrollbar-thumb': {
|
|
947
|
-
background:
|
|
1150
|
+
background: style.tokenSchema.color.border.muted,
|
|
948
1151
|
borderRadius: 3
|
|
949
1152
|
}
|
|
950
1153
|
}),
|
|
@@ -970,8 +1173,8 @@ function TopBar({
|
|
|
970
1173
|
height: TOPBAR_HEIGHT,
|
|
971
1174
|
paddingInline: '24px',
|
|
972
1175
|
gap: '14px',
|
|
973
|
-
backgroundColor:
|
|
974
|
-
borderBottom:
|
|
1176
|
+
backgroundColor: style.tokenSchema.color.background.canvas,
|
|
1177
|
+
borderBottom: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
975
1178
|
flexShrink: 0,
|
|
976
1179
|
zIndex: 30
|
|
977
1180
|
}),
|
|
@@ -979,6 +1182,7 @@ function TopBar({
|
|
|
979
1182
|
onClick: onMenuClick,
|
|
980
1183
|
"aria-label": isSidebarOpen ? 'Close menu' : 'Open menu',
|
|
981
1184
|
"aria-expanded": isSidebarOpen,
|
|
1185
|
+
"aria-controls": "nixxie-sidebar",
|
|
982
1186
|
className: style.css({
|
|
983
1187
|
display: 'inline-flex',
|
|
984
1188
|
alignItems: 'center',
|
|
@@ -986,15 +1190,15 @@ function TopBar({
|
|
|
986
1190
|
width: 32,
|
|
987
1191
|
height: 32,
|
|
988
1192
|
borderRadius: 6,
|
|
989
|
-
border:
|
|
1193
|
+
border: `1px solid ${style.tokenSchema.color.border.muted}`,
|
|
990
1194
|
background: 'transparent',
|
|
991
1195
|
cursor: 'pointer',
|
|
992
1196
|
flexShrink: 0,
|
|
993
|
-
color:
|
|
1197
|
+
color: style.tokenSchema.color.foreground.neutralTertiary,
|
|
994
1198
|
transition: 'color 130ms, background 130ms',
|
|
995
1199
|
'&:hover': {
|
|
996
|
-
background:
|
|
997
|
-
color:
|
|
1200
|
+
background: style.tokenSchema.color.background.surfaceSecondary,
|
|
1201
|
+
color: style.tokenSchema.color.foreground.neutralEmphasis
|
|
998
1202
|
},
|
|
999
1203
|
'@media (min-width: 768px)': {
|
|
1000
1204
|
display: 'none'
|
|
@@ -1055,6 +1259,8 @@ function TopBar({
|
|
|
1055
1259
|
// ---- Main content area ----
|
|
1056
1260
|
function MainContent(props) {
|
|
1057
1261
|
return /*#__PURE__*/jsxRuntime.jsx("main", {
|
|
1262
|
+
id: "main-content",
|
|
1263
|
+
tabIndex: -1,
|
|
1058
1264
|
className: style.css({
|
|
1059
1265
|
flex: 1,
|
|
1060
1266
|
display: 'flex',
|
|
@@ -1078,11 +1284,11 @@ function ContentScroller(props) {
|
|
|
1078
1284
|
width: 5
|
|
1079
1285
|
},
|
|
1080
1286
|
'&::-webkit-scrollbar-thumb': {
|
|
1081
|
-
background:
|
|
1287
|
+
background: style.tokenSchema.color.border.muted,
|
|
1082
1288
|
borderRadius: 4
|
|
1083
1289
|
},
|
|
1084
1290
|
'&::-webkit-scrollbar-thumb:hover': {
|
|
1085
|
-
background:
|
|
1291
|
+
background: style.tokenSchema.color.border.emphasis
|
|
1086
1292
|
}
|
|
1087
1293
|
}),
|
|
1088
1294
|
...props
|
|
@@ -1121,7 +1327,7 @@ function PageContainer({
|
|
|
1121
1327
|
children: /*#__PURE__*/jsxRuntime.jsx("title", {
|
|
1122
1328
|
children: title ? `Nixxie – ${title}` : 'Nixxie'
|
|
1123
1329
|
}, "title")
|
|
1124
|
-
}), /*#__PURE__*/jsxRuntime.jsx(Sidebar, {
|
|
1330
|
+
}), /*#__PURE__*/jsxRuntime.jsx(SkipLink, {}), /*#__PURE__*/jsxRuntime.jsx(Sidebar, {
|
|
1125
1331
|
isOpen: isSidebarOpen,
|
|
1126
1332
|
onClose: () => setSidebarOpen(false),
|
|
1127
1333
|
onCmdK: () => setCmdOpen(v => !v)
|