@furystack/shades-common-components 13.0.1 → 13.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/CHANGELOG.md +67 -0
- package/esm/components/app-bar.d.ts.map +1 -1
- package/esm/components/app-bar.js +12 -3
- package/esm/components/app-bar.js.map +1 -1
- package/esm/components/avatar.d.ts.map +1 -1
- package/esm/components/avatar.js +3 -5
- package/esm/components/avatar.js.map +1 -1
- package/esm/components/cache-view.d.ts +19 -27
- package/esm/components/cache-view.d.ts.map +1 -1
- package/esm/components/cache-view.js +2 -20
- package/esm/components/cache-view.js.map +1 -1
- package/esm/components/cache-view.spec.js +44 -0
- package/esm/components/cache-view.spec.js.map +1 -1
- package/esm/components/command-palette/command-palette-input.d.ts +1 -2
- package/esm/components/command-palette/command-palette-input.d.ts.map +1 -1
- package/esm/components/command-palette/command-palette-input.js +14 -36
- package/esm/components/command-palette/command-palette-input.js.map +1 -1
- package/esm/components/command-palette/command-palette-input.spec.js +14 -116
- package/esm/components/command-palette/command-palette-input.spec.js.map +1 -1
- package/esm/components/command-palette/index.d.ts.map +1 -1
- package/esm/components/command-palette/index.js +3 -0
- package/esm/components/command-palette/index.js.map +1 -1
- package/esm/components/drawer/index.d.ts.map +1 -1
- package/esm/components/drawer/index.js +4 -0
- package/esm/components/drawer/index.js.map +1 -1
- package/esm/components/drawer/index.spec.js +47 -0
- package/esm/components/drawer/index.spec.js.map +1 -1
- package/esm/components/noty-list.d.ts.map +1 -1
- package/esm/components/noty-list.js +1 -3
- package/esm/components/noty-list.js.map +1 -1
- package/esm/services/css-variable-theme.d.ts +1 -1
- package/esm/services/css-variable-theme.d.ts.map +1 -1
- package/esm/services/css-variable-theme.js +5 -5
- package/esm/services/css-variable-theme.js.map +1 -1
- package/esm/services/css-variable-theme.spec.js +29 -1
- package/esm/services/css-variable-theme.spec.js.map +1 -1
- package/esm/services/layout-service.d.ts +8 -0
- package/esm/services/layout-service.d.ts.map +1 -1
- package/esm/services/layout-service.js +16 -0
- package/esm/services/layout-service.js.map +1 -1
- package/esm/services/layout-service.spec.js +55 -0
- package/esm/services/layout-service.spec.js.map +1 -1
- package/esm/services/theme-provider-service.d.ts +11 -10
- package/esm/services/theme-provider-service.d.ts.map +1 -1
- package/esm/services/theme-provider-service.js +3 -2
- package/esm/services/theme-provider-service.js.map +1 -1
- package/esm/services/theme-provider-service.spec.js +35 -1
- package/esm/services/theme-provider-service.spec.js.map +1 -1
- package/esm/themes/architect-theme.d.ts +1 -0
- package/esm/themes/architect-theme.d.ts.map +1 -1
- package/esm/themes/architect-theme.js +1 -0
- package/esm/themes/architect-theme.js.map +1 -1
- package/esm/themes/auditore-theme.d.ts +1 -0
- package/esm/themes/auditore-theme.d.ts.map +1 -1
- package/esm/themes/auditore-theme.js +1 -0
- package/esm/themes/auditore-theme.js.map +1 -1
- package/esm/themes/black-mesa-theme.d.ts +1 -0
- package/esm/themes/black-mesa-theme.d.ts.map +1 -1
- package/esm/themes/black-mesa-theme.js +1 -0
- package/esm/themes/black-mesa-theme.js.map +1 -1
- package/esm/themes/default-dark-theme.d.ts +1 -0
- package/esm/themes/default-dark-theme.d.ts.map +1 -1
- package/esm/themes/default-dark-theme.js +1 -0
- package/esm/themes/default-dark-theme.js.map +1 -1
- package/esm/themes/default-light-theme.d.ts +1 -0
- package/esm/themes/default-light-theme.d.ts.map +1 -1
- package/esm/themes/default-light-theme.js +1 -0
- package/esm/themes/default-light-theme.js.map +1 -1
- package/esm/themes/dragonborn-theme.d.ts +1 -0
- package/esm/themes/dragonborn-theme.d.ts.map +1 -1
- package/esm/themes/dragonborn-theme.js +1 -0
- package/esm/themes/dragonborn-theme.js.map +1 -1
- package/esm/themes/hawkins-theme.d.ts +1 -0
- package/esm/themes/hawkins-theme.d.ts.map +1 -1
- package/esm/themes/hawkins-theme.js +1 -0
- package/esm/themes/hawkins-theme.js.map +1 -1
- package/esm/themes/jedi-theme.d.ts +1 -0
- package/esm/themes/jedi-theme.d.ts.map +1 -1
- package/esm/themes/jedi-theme.js +1 -0
- package/esm/themes/jedi-theme.js.map +1 -1
- package/esm/themes/neon-runner-theme.d.ts +1 -0
- package/esm/themes/neon-runner-theme.d.ts.map +1 -1
- package/esm/themes/neon-runner-theme.js +1 -0
- package/esm/themes/neon-runner-theme.js.map +1 -1
- package/esm/themes/plumber-theme.d.ts +1 -0
- package/esm/themes/plumber-theme.d.ts.map +1 -1
- package/esm/themes/plumber-theme.js +1 -0
- package/esm/themes/plumber-theme.js.map +1 -1
- package/esm/themes/replicant-theme.d.ts +1 -0
- package/esm/themes/replicant-theme.d.ts.map +1 -1
- package/esm/themes/replicant-theme.js +1 -0
- package/esm/themes/replicant-theme.js.map +1 -1
- package/esm/themes/sandworm-theme.d.ts +1 -0
- package/esm/themes/sandworm-theme.d.ts.map +1 -1
- package/esm/themes/sandworm-theme.js +1 -0
- package/esm/themes/sandworm-theme.js.map +1 -1
- package/esm/themes/shadow-broker-theme.d.ts +1 -0
- package/esm/themes/shadow-broker-theme.d.ts.map +1 -1
- package/esm/themes/shadow-broker-theme.js +1 -0
- package/esm/themes/shadow-broker-theme.js.map +1 -1
- package/esm/themes/sith-theme.d.ts +1 -0
- package/esm/themes/sith-theme.d.ts.map +1 -1
- package/esm/themes/sith-theme.js +1 -0
- package/esm/themes/sith-theme.js.map +1 -1
- package/esm/themes/vault-dweller-theme.d.ts +1 -0
- package/esm/themes/vault-dweller-theme.d.ts.map +1 -1
- package/esm/themes/vault-dweller-theme.js +1 -0
- package/esm/themes/vault-dweller-theme.js.map +1 -1
- package/esm/themes/wild-hunt-theme.d.ts +1 -0
- package/esm/themes/wild-hunt-theme.d.ts.map +1 -1
- package/esm/themes/wild-hunt-theme.js +1 -0
- package/esm/themes/wild-hunt-theme.js.map +1 -1
- package/esm/themes/xenomorph-theme.d.ts +1 -0
- package/esm/themes/xenomorph-theme.d.ts.map +1 -1
- package/esm/themes/xenomorph-theme.js +1 -0
- package/esm/themes/xenomorph-theme.js.map +1 -1
- package/package.json +1 -1
- package/src/components/app-bar.tsx +12 -3
- package/src/components/avatar.tsx +20 -5
- package/src/components/cache-view.spec.tsx +63 -0
- package/src/components/cache-view.tsx +41 -9
- package/src/components/command-palette/command-palette-input.spec.tsx +14 -156
- package/src/components/command-palette/command-palette-input.tsx +13 -45
- package/src/components/command-palette/index.tsx +4 -0
- package/src/components/drawer/index.spec.tsx +64 -0
- package/src/components/drawer/index.tsx +5 -0
- package/src/components/noty-list.tsx +1 -3
- package/src/services/css-variable-theme.spec.ts +43 -1
- package/src/services/css-variable-theme.ts +5 -5
- package/src/services/layout-service.spec.ts +74 -0
- package/src/services/layout-service.ts +18 -0
- package/src/services/theme-provider-service.spec.ts +49 -1
- package/src/services/theme-provider-service.ts +12 -11
- package/src/themes/architect-theme.ts +1 -0
- package/src/themes/auditore-theme.ts +1 -0
- package/src/themes/black-mesa-theme.ts +1 -0
- package/src/themes/default-dark-theme.ts +1 -0
- package/src/themes/default-light-theme.ts +1 -0
- package/src/themes/dragonborn-theme.ts +1 -0
- package/src/themes/hawkins-theme.ts +1 -0
- package/src/themes/jedi-theme.ts +1 -0
- package/src/themes/neon-runner-theme.ts +1 -0
- package/src/themes/plumber-theme.ts +1 -0
- package/src/themes/replicant-theme.ts +1 -0
- package/src/themes/sandworm-theme.ts +1 -0
- package/src/themes/shadow-broker-theme.ts +1 -0
- package/src/themes/sith-theme.ts +1 -0
- package/src/themes/vault-dweller-theme.ts +1 -0
- package/src/themes/wild-hunt-theme.ts +1 -0
- package/src/themes/xenomorph-theme.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xenomorph-theme.d.ts","sourceRoot":"","sources":["../../src/themes/xenomorph-theme.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"xenomorph-theme.d.ts","sourceRoot":"","sources":["../../src/themes/xenomorph-theme.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgHV,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xenomorph-theme.js","sourceRoot":"","sources":["../../src/themes/xenomorph-theme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAGzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE;QACJ,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,2BAA2B;QACtC,QAAQ,EAAE,2BAA2B;KACtC;IACD,MAAM,EAAE;QACN,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,yBAAyB;QAChC,QAAQ,EAAE,0BAA0B;QACpC,QAAQ,EAAE,0BAA0B;QACpC,kBAAkB,EAAE,2BAA2B;KAChD;IACD,UAAU,EAAE;QACV,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,SAAS;QAChB,UAAU,EAAE,EAAE;KACf;IACD,OAAO,EAAE,gBAAgB;IACzB,OAAO,EAAE,0BAA0B;IACnC,MAAM,EAAE;QACN,eAAe,EAAE,0BAA0B;QAC3C,kBAAkB,EAAE,0BAA0B;QAC9C,gBAAgB,EAAE,yBAAyB;QAC3C,SAAS,EAAE,oCAAoC;QAC/C,eAAe,EAAE,KAAK;QACtB,QAAQ,EAAE,qBAAqB;QAC/B,YAAY,EAAE,0BAA0B;KACzC;IACD,KAAK,EAAE;QACL,YAAY,EAAE;YACZ,EAAE,EAAE,KAAK;YACT,EAAE,EAAE,KAAK;YACT,EAAE,EAAE,KAAK;YACT,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,KAAK;SACZ;QACD,WAAW,EAAE,KAAK;KACnB;IACD,OAAO,EAAE;QACP,IAAI,EAAE,MAAM;QACZ,EAAE,EAAE,gEAAgE;QACpE,EAAE,EAAE,kEAAkE;QACtE,EAAE,EAAE,iEAAiE;QACrE,EAAE,EAAE,mEAAmE;KACxE;IACD,UAAU,EAAE;QACV,UAAU,EAAE,qDAAqD;QACjE,QAAQ,EAAE;YACR,EAAE,EAAE,MAAM;YACV,EAAE,EAAE,MAAM;YACV,EAAE,EAAE,MAAM;YACV,EAAE,EAAE,MAAM;YACV,EAAE,EAAE,MAAM;YACV,GAAG,EAAE,MAAM;YACX,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,MAAM;SACd;QACD,UAAU,EAAE;YACV,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,KAAK;YACb,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,KAAK;SACZ;QACD,UAAU,EAAE;YACV,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,KAAK;SACf;QACD,aAAa,EAAE;YACb,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,KAAK;SACd;
|
|
1
|
+
{"version":3,"file":"xenomorph-theme.js","sourceRoot":"","sources":["../../src/themes/xenomorph-theme.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -5,9 +5,6 @@ export const AppBar = Shade({
|
|
|
5
5
|
shadowDomName: 'shade-app-bar',
|
|
6
6
|
css: {
|
|
7
7
|
width: '100%',
|
|
8
|
-
background: `color-mix(in srgb, ${cssVariableTheme.background.paper} 85%, transparent)`,
|
|
9
|
-
backgroundImage: cssVariableTheme.background.paperImage,
|
|
10
|
-
backdropFilter: `blur(${cssVariableTheme.effects.blurLg})`,
|
|
11
8
|
display: 'flex',
|
|
12
9
|
justifyContent: 'flex-start',
|
|
13
10
|
alignItems: 'center',
|
|
@@ -18,6 +15,18 @@ export const AppBar = Shade({
|
|
|
18
15
|
zIndex: '1',
|
|
19
16
|
fontFamily: cssVariableTheme.typography.fontFamily,
|
|
20
17
|
color: cssVariableTheme.text.primary,
|
|
18
|
+
// backdrop-filter on the host would create a containing block for position:fixed
|
|
19
|
+
// descendants (per CSS spec), breaking Dropdown overlays inside the AppBar.
|
|
20
|
+
// Using a pseudo-element avoids this while preserving the visual effect.
|
|
21
|
+
'&::before': {
|
|
22
|
+
content: '""',
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
inset: '0',
|
|
25
|
+
zIndex: '-1',
|
|
26
|
+
background: `color-mix(in srgb, ${cssVariableTheme.background.paper} 85%, transparent)`,
|
|
27
|
+
backgroundImage: cssVariableTheme.background.paperImage,
|
|
28
|
+
backdropFilter: `blur(${cssVariableTheme.effects.blurLg})`,
|
|
29
|
+
},
|
|
21
30
|
'&[data-visible]': {
|
|
22
31
|
opacity: '1',
|
|
23
32
|
},
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { PartialElement } from '@furystack/shades'
|
|
2
2
|
import { Shade, createComponent } from '@furystack/shades'
|
|
3
3
|
import { cssVariableTheme } from '../services/css-variable-theme.js'
|
|
4
|
-
import { Icon } from './icons/icon.js'
|
|
5
4
|
import { user as userIcon } from './icons/icon-definitions.js'
|
|
6
5
|
|
|
7
6
|
export type AvatarProps = { avatarUrl: string; fallback?: JSX.Element } & PartialElement<HTMLDivElement>
|
|
@@ -37,14 +36,13 @@ export const Avatar = Shade<AvatarProps>({
|
|
|
37
36
|
display: 'flex',
|
|
38
37
|
alignItems: 'center',
|
|
39
38
|
justifyContent: 'center',
|
|
40
|
-
width: '
|
|
41
|
-
height: '
|
|
39
|
+
width: '100%',
|
|
40
|
+
height: '100%',
|
|
42
41
|
borderRadius: cssVariableTheme.shape.borderRadius.full,
|
|
43
42
|
background: `color-mix(in srgb, ${cssVariableTheme.palette.primary.main} 20%, transparent)`,
|
|
44
43
|
backdropFilter: 'blur(10px)',
|
|
45
44
|
textAlign: 'center',
|
|
46
45
|
userSelect: 'none',
|
|
47
|
-
fontSize: '48px',
|
|
48
46
|
lineHeight: '1',
|
|
49
47
|
},
|
|
50
48
|
},
|
|
@@ -59,7 +57,24 @@ export const Avatar = Shade<AvatarProps>({
|
|
|
59
57
|
if (hasError) {
|
|
60
58
|
return (
|
|
61
59
|
<div className="avatar-fallback-container">
|
|
62
|
-
<div className="avatar-fallback-icon">
|
|
60
|
+
<div className="avatar-fallback-icon">
|
|
61
|
+
{props.fallback || (
|
|
62
|
+
<svg
|
|
63
|
+
width="100%"
|
|
64
|
+
height="100%"
|
|
65
|
+
viewBox={userIcon.viewBox ?? '0 0 24 24'}
|
|
66
|
+
fill="none"
|
|
67
|
+
stroke="currentColor"
|
|
68
|
+
stroke-width="2"
|
|
69
|
+
stroke-linecap="round"
|
|
70
|
+
stroke-linejoin="round"
|
|
71
|
+
>
|
|
72
|
+
{userIcon.paths.map((p) => (
|
|
73
|
+
<path d={p.d} />
|
|
74
|
+
))}
|
|
75
|
+
</svg>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
63
78
|
</div>
|
|
64
79
|
)
|
|
65
80
|
}
|
|
@@ -10,6 +10,15 @@ const TestContent = Shade<{ data: CacheWithValue<string> }>({
|
|
|
10
10
|
render: ({ props }) => <span className="content-value">{props.data.value}</span>,
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
+
const TestContentWithLabel = Shade<{ data: CacheWithValue<string>; label: string }>({
|
|
14
|
+
shadowDomName: 'test-cache-content-with-label',
|
|
15
|
+
render: ({ props }) => (
|
|
16
|
+
<span className="content-value">
|
|
17
|
+
{props.label}: {props.data.value}
|
|
18
|
+
</span>
|
|
19
|
+
),
|
|
20
|
+
})
|
|
21
|
+
|
|
13
22
|
const renderCacheView = async (
|
|
14
23
|
cache: Cache<string, [string]>,
|
|
15
24
|
args: [string],
|
|
@@ -210,4 +219,58 @@ describe('CacheView', () => {
|
|
|
210
219
|
cache[Symbol.dispose]()
|
|
211
220
|
})
|
|
212
221
|
})
|
|
222
|
+
|
|
223
|
+
describe('contentProps', () => {
|
|
224
|
+
it('should forward contentProps to the content component', async () => {
|
|
225
|
+
const cache = new Cache<string, [string]>({ load: async (key) => `Hello ${key}` })
|
|
226
|
+
await cache.get('world')
|
|
227
|
+
|
|
228
|
+
const el = (
|
|
229
|
+
<div>
|
|
230
|
+
<CacheView
|
|
231
|
+
cache={cache}
|
|
232
|
+
args={['world']}
|
|
233
|
+
content={TestContentWithLabel}
|
|
234
|
+
contentProps={{ label: 'Greeting' }}
|
|
235
|
+
/>
|
|
236
|
+
</div>
|
|
237
|
+
)
|
|
238
|
+
const cacheView = el.firstElementChild as JSX.Element
|
|
239
|
+
cacheView.updateComponent()
|
|
240
|
+
await flushUpdates()
|
|
241
|
+
|
|
242
|
+
const contentEl = cacheView.querySelector('test-cache-content-with-label') as JSX.Element
|
|
243
|
+
expect(contentEl).not.toBeNull()
|
|
244
|
+
contentEl.updateComponent()
|
|
245
|
+
await flushUpdates()
|
|
246
|
+
const valueEl = contentEl.querySelector('.content-value')
|
|
247
|
+
expect(valueEl?.textContent).toBe('Greeting: Hello world')
|
|
248
|
+
cache[Symbol.dispose]()
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('should forward contentProps when cache entry is obsolete', async () => {
|
|
252
|
+
const loadFn = vi.fn(async (key: string) => `Hello ${key}`)
|
|
253
|
+
const cache = new Cache<string, [string]>({ load: loadFn })
|
|
254
|
+
await cache.get('world')
|
|
255
|
+
cache.setObsolete('world')
|
|
256
|
+
|
|
257
|
+
const el = (
|
|
258
|
+
<div>
|
|
259
|
+
<CacheView cache={cache} args={['world']} content={TestContentWithLabel} contentProps={{ label: 'Stale' }} />
|
|
260
|
+
</div>
|
|
261
|
+
)
|
|
262
|
+
const cacheView = el.firstElementChild as JSX.Element
|
|
263
|
+
cacheView.updateComponent()
|
|
264
|
+
await flushUpdates()
|
|
265
|
+
|
|
266
|
+
const contentEl = cacheView.querySelector('test-cache-content-with-label') as JSX.Element
|
|
267
|
+
expect(contentEl).not.toBeNull()
|
|
268
|
+
contentEl.updateComponent()
|
|
269
|
+
await flushUpdates()
|
|
270
|
+
const valueEl = contentEl.querySelector('.content-value')
|
|
271
|
+
expect(valueEl?.textContent).toBe('Stale: Hello world')
|
|
272
|
+
expect(loadFn).toHaveBeenCalledTimes(2)
|
|
273
|
+
cache[Symbol.dispose]()
|
|
274
|
+
})
|
|
275
|
+
})
|
|
213
276
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Cache, CacheWithValue } from '@furystack/cache'
|
|
2
2
|
import { hasCacheValue, isFailedCacheResult, isObsoleteCacheResult } from '@furystack/cache'
|
|
3
|
-
import type { ShadeComponent } from '@furystack/shades'
|
|
3
|
+
import type { PartialElement, ShadeComponent } from '@furystack/shades'
|
|
4
4
|
import { Shade, createComponent } from '@furystack/shades'
|
|
5
5
|
|
|
6
6
|
import { cssVariableTheme } from '../services/css-variable-theme.js'
|
|
@@ -11,14 +11,19 @@ import { Result } from './result.js'
|
|
|
11
11
|
* Props for the CacheView component.
|
|
12
12
|
* @typeParam TData - The type of data stored in the cache
|
|
13
13
|
* @typeParam TArgs - The tuple type of arguments used to identify the cache entry
|
|
14
|
+
* @typeParam TContentProps - The full props type of the content component (must include `data`)
|
|
14
15
|
*/
|
|
15
|
-
export type CacheViewProps<
|
|
16
|
+
export type CacheViewProps<
|
|
17
|
+
TData,
|
|
18
|
+
TArgs extends any[],
|
|
19
|
+
TContentProps extends { data: CacheWithValue<TData> } = { data: CacheWithValue<TData> },
|
|
20
|
+
> = {
|
|
16
21
|
/** The cache instance to observe and control */
|
|
17
22
|
cache: Cache<TData, TArgs>
|
|
18
23
|
/** The arguments identifying which cache entry to display */
|
|
19
24
|
args: TArgs
|
|
20
|
-
/** Shades component rendered when a value is available (loaded or obsolete).
|
|
21
|
-
content: ShadeComponent<
|
|
25
|
+
/** Shades component rendered when a value is available (loaded or obsolete). */
|
|
26
|
+
content: ShadeComponent<TContentProps>
|
|
22
27
|
/** Optional custom loader element. Default: null (nothing shown when loading). */
|
|
23
28
|
loader?: JSX.Element
|
|
24
29
|
/**
|
|
@@ -27,7 +32,9 @@ export type CacheViewProps<TData, TArgs extends any[]> = {
|
|
|
27
32
|
* If not provided, a default Result + retry Button is shown.
|
|
28
33
|
*/
|
|
29
34
|
error?: (error: unknown, retry: () => void) => JSX.Element
|
|
30
|
-
}
|
|
35
|
+
} & (keyof Omit<TContentProps, 'data' | keyof PartialElement<HTMLElement>> extends never
|
|
36
|
+
? { contentProps?: never }
|
|
37
|
+
: { contentProps: Omit<TContentProps, 'data' | keyof PartialElement<HTMLElement>> })
|
|
31
38
|
|
|
32
39
|
const getDefaultErrorUi = (error: unknown, retry: () => void): JSX.Element =>
|
|
33
40
|
(
|
|
@@ -55,15 +62,33 @@ const getDefaultErrorUi = (error: unknown, retry: () => void): JSX.Element =>
|
|
|
55
62
|
* })
|
|
56
63
|
*
|
|
57
64
|
* <CacheView cache={userCache} args={[userId]} content={MyContent} />
|
|
65
|
+
*
|
|
66
|
+
* // With custom content props
|
|
67
|
+
* const MyContentWithLabel = Shade<{ data: CacheWithValue<User>; label: string }>({
|
|
68
|
+
* shadowDomName: 'my-content-with-label',
|
|
69
|
+
* render: ({ props }) => <div>{props.label}: {props.data.value.name}</div>,
|
|
70
|
+
* })
|
|
71
|
+
*
|
|
72
|
+
* <CacheView cache={userCache} args={[userId]} content={MyContentWithLabel} contentProps={{ label: 'User' }} />
|
|
58
73
|
* ```
|
|
59
74
|
*/
|
|
60
|
-
|
|
75
|
+
/** @internal Ungeneric props used by the Shade runtime; the public generic signature is applied via the export cast. */
|
|
76
|
+
type InternalCacheViewProps = {
|
|
77
|
+
cache: Cache<unknown, unknown[]>
|
|
78
|
+
args: unknown[]
|
|
79
|
+
content: ShadeComponent<{ data: CacheWithValue<unknown> }>
|
|
80
|
+
contentProps?: Record<string, unknown>
|
|
81
|
+
loader?: JSX.Element
|
|
82
|
+
error?: (error: unknown, retry: () => void) => JSX.Element
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const CacheView = Shade<InternalCacheViewProps>({
|
|
61
86
|
shadowDomName: 'shade-cache-view',
|
|
62
87
|
css: {
|
|
63
88
|
fontFamily: cssVariableTheme.typography.fontFamily,
|
|
64
89
|
},
|
|
65
90
|
render: ({ props, useObservable, useState }): JSX.Element | null => {
|
|
66
|
-
const { cache, args, content, loader, error } = props
|
|
91
|
+
const { cache, args, content, loader, error, contentProps } = props
|
|
67
92
|
|
|
68
93
|
const argsKey = JSON.stringify(args)
|
|
69
94
|
const observable = cache.getObservable(...args)
|
|
@@ -96,12 +121,19 @@ export const CacheView: <TData, TArgs extends any[]>(props: CacheViewProps<TData
|
|
|
96
121
|
} else if (lastReloadedArgsKey !== null) {
|
|
97
122
|
setLastReloadedArgsKey(null)
|
|
98
123
|
}
|
|
99
|
-
return createComponent(content
|
|
124
|
+
return createComponent(content, {
|
|
100
125
|
data: result,
|
|
126
|
+
...(contentProps ?? {}),
|
|
101
127
|
}) as unknown as JSX.Element
|
|
102
128
|
}
|
|
103
129
|
|
|
104
130
|
// 3. Loading last
|
|
105
131
|
return loader ?? null
|
|
106
132
|
},
|
|
107
|
-
})
|
|
133
|
+
}) as unknown as <
|
|
134
|
+
TData,
|
|
135
|
+
TArgs extends any[],
|
|
136
|
+
TContentProps extends { data: CacheWithValue<TData> } = { data: CacheWithValue<TData> },
|
|
137
|
+
>(
|
|
138
|
+
props: CacheViewProps<TData, TArgs, TContentProps>,
|
|
139
|
+
) => JSX.Element
|
|
@@ -6,42 +6,14 @@ import { CommandPaletteInput } from './command-palette-input.js'
|
|
|
6
6
|
import { CommandPaletteManager } from './command-palette-manager.js'
|
|
7
7
|
|
|
8
8
|
describe('CommandPaletteInput', () => {
|
|
9
|
-
let originalAnimate: typeof Element.prototype.animate
|
|
10
|
-
let animateCalls: Array<{ keyframes: unknown; options: unknown }>
|
|
11
|
-
|
|
12
9
|
beforeEach(() => {
|
|
13
10
|
vi.useFakeTimers()
|
|
14
11
|
document.body.innerHTML = '<div id="root"></div>'
|
|
15
|
-
animateCalls = []
|
|
16
|
-
originalAnimate = Element.prototype.animate
|
|
17
|
-
|
|
18
|
-
Element.prototype.animate = vi.fn(
|
|
19
|
-
(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions) => {
|
|
20
|
-
animateCalls.push({ keyframes, options })
|
|
21
|
-
const mockAnimation = {
|
|
22
|
-
onfinish: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
23
|
-
oncancel: null as ((event: AnimationPlaybackEvent) => void) | null,
|
|
24
|
-
cancel: vi.fn(),
|
|
25
|
-
play: vi.fn(),
|
|
26
|
-
pause: vi.fn(),
|
|
27
|
-
finish: vi.fn(),
|
|
28
|
-
addEventListener: vi.fn(),
|
|
29
|
-
removeEventListener: vi.fn(),
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
setTimeout(() => {
|
|
33
|
-
mockAnimation.onfinish?.({} as AnimationPlaybackEvent)
|
|
34
|
-
}, 10)
|
|
35
|
-
|
|
36
|
-
return mockAnimation as unknown as Animation
|
|
37
|
-
},
|
|
38
|
-
) as typeof Element.prototype.animate
|
|
39
12
|
})
|
|
40
13
|
|
|
41
14
|
afterEach(() => {
|
|
42
15
|
vi.useRealTimers()
|
|
43
16
|
document.body.innerHTML = ''
|
|
44
|
-
Element.prototype.animate = originalAnimate
|
|
45
17
|
vi.restoreAllMocks()
|
|
46
18
|
})
|
|
47
19
|
|
|
@@ -89,7 +61,7 @@ describe('CommandPaletteInput', () => {
|
|
|
89
61
|
})
|
|
90
62
|
})
|
|
91
63
|
|
|
92
|
-
it('should
|
|
64
|
+
it('should always have width 100%', async () => {
|
|
93
65
|
await usingAsync(new Injector(), async (injector) => {
|
|
94
66
|
await usingAsync(createManager(), async (manager) => {
|
|
95
67
|
manager.isOpened.setValue(false)
|
|
@@ -104,15 +76,15 @@ describe('CommandPaletteInput', () => {
|
|
|
104
76
|
await flushUpdates()
|
|
105
77
|
|
|
106
78
|
const component = document.querySelector('shades-command-palette-input') as HTMLElement
|
|
107
|
-
|
|
79
|
+
const computedStyle = window.getComputedStyle(component)
|
|
80
|
+
expect(computedStyle.width).toBe('100%')
|
|
108
81
|
})
|
|
109
82
|
})
|
|
110
83
|
})
|
|
111
84
|
|
|
112
|
-
it('should have
|
|
85
|
+
it('should have overflow hidden style', async () => {
|
|
113
86
|
await usingAsync(new Injector(), async (injector) => {
|
|
114
87
|
await usingAsync(createManager(), async (manager) => {
|
|
115
|
-
manager.isOpened.setValue(true)
|
|
116
88
|
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
117
89
|
|
|
118
90
|
initializeShadeRoot({
|
|
@@ -124,73 +96,13 @@ describe('CommandPaletteInput', () => {
|
|
|
124
96
|
await flushUpdates()
|
|
125
97
|
|
|
126
98
|
const component = document.querySelector('shades-command-palette-input') as HTMLElement
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
})
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it('should animate width when opening', async () => {
|
|
133
|
-
await usingAsync(new Injector(), async (injector) => {
|
|
134
|
-
await usingAsync(createManager(), async (manager) => {
|
|
135
|
-
manager.isOpened.setValue(false)
|
|
136
|
-
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
137
|
-
|
|
138
|
-
initializeShadeRoot({
|
|
139
|
-
injector,
|
|
140
|
-
rootElement,
|
|
141
|
-
jsxElement: <CommandPaletteInput manager={manager} />,
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
await flushUpdates()
|
|
145
|
-
animateCalls = []
|
|
146
|
-
|
|
147
|
-
manager.isOpened.setValue(true)
|
|
148
|
-
await flushUpdates()
|
|
149
|
-
|
|
150
|
-
const widthAnimation = animateCalls.find(
|
|
151
|
-
(call) =>
|
|
152
|
-
Array.isArray(call.keyframes) &&
|
|
153
|
-
call.keyframes.some((kf: Keyframe) => kf.width === '0%') &&
|
|
154
|
-
call.keyframes.some((kf: Keyframe) => kf.width === '100%'),
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
expect(widthAnimation).toBeDefined()
|
|
158
|
-
expect((widthAnimation?.options as KeyframeAnimationOptions)?.duration).toBe(300)
|
|
159
|
-
})
|
|
160
|
-
})
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
it('should animate width when closing', async () => {
|
|
164
|
-
await usingAsync(new Injector(), async (injector) => {
|
|
165
|
-
await usingAsync(createManager(), async (manager) => {
|
|
166
|
-
manager.isOpened.setValue(true)
|
|
167
|
-
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
168
|
-
|
|
169
|
-
initializeShadeRoot({
|
|
170
|
-
injector,
|
|
171
|
-
rootElement,
|
|
172
|
-
jsxElement: <CommandPaletteInput manager={manager} />,
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
await flushUpdates()
|
|
176
|
-
animateCalls = []
|
|
177
|
-
|
|
178
|
-
manager.isOpened.setValue(false)
|
|
179
|
-
await flushUpdates()
|
|
180
|
-
|
|
181
|
-
const widthAnimation = animateCalls.find(
|
|
182
|
-
(call) =>
|
|
183
|
-
Array.isArray(call.keyframes) &&
|
|
184
|
-
call.keyframes.some((kf: Keyframe) => kf.width === '100%') &&
|
|
185
|
-
call.keyframes.some((kf: Keyframe) => kf.width === '0%'),
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
expect(widthAnimation).toBeDefined()
|
|
99
|
+
const computedStyle = window.getComputedStyle(component)
|
|
100
|
+
expect(computedStyle.overflow).toBe('hidden')
|
|
189
101
|
})
|
|
190
102
|
})
|
|
191
103
|
})
|
|
192
104
|
|
|
193
|
-
it('should
|
|
105
|
+
it('should focus input when opened', async () => {
|
|
194
106
|
await usingAsync(new Injector(), async (injector) => {
|
|
195
107
|
await usingAsync(createManager(), async (manager) => {
|
|
196
108
|
manager.isOpened.setValue(false)
|
|
@@ -206,12 +118,12 @@ describe('CommandPaletteInput', () => {
|
|
|
206
118
|
|
|
207
119
|
const component = document.querySelector('shades-command-palette-input') as HTMLElement
|
|
208
120
|
const inputElement = component?.querySelector('input') as HTMLInputElement
|
|
209
|
-
|
|
121
|
+
const focusSpy = vi.spyOn(inputElement, 'focus')
|
|
210
122
|
|
|
211
123
|
manager.isOpened.setValue(true)
|
|
212
124
|
await flushUpdates()
|
|
213
125
|
|
|
214
|
-
expect(
|
|
126
|
+
expect(focusSpy).toHaveBeenCalled()
|
|
215
127
|
})
|
|
216
128
|
})
|
|
217
129
|
})
|
|
@@ -236,35 +148,13 @@ describe('CommandPaletteInput', () => {
|
|
|
236
148
|
|
|
237
149
|
manager.isOpened.setValue(false)
|
|
238
150
|
await flushUpdates()
|
|
239
|
-
await vi.advanceTimersByTimeAsync(20)
|
|
240
|
-
await flushUpdates()
|
|
241
151
|
|
|
242
152
|
expect(inputElement.value).toBe('')
|
|
243
153
|
})
|
|
244
154
|
})
|
|
245
155
|
})
|
|
246
156
|
|
|
247
|
-
it('should
|
|
248
|
-
await usingAsync(new Injector(), async (injector) => {
|
|
249
|
-
await usingAsync(createManager(), async (manager) => {
|
|
250
|
-
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
251
|
-
|
|
252
|
-
initializeShadeRoot({
|
|
253
|
-
injector,
|
|
254
|
-
rootElement,
|
|
255
|
-
jsxElement: <CommandPaletteInput manager={manager} />,
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
await flushUpdates()
|
|
259
|
-
|
|
260
|
-
const component = document.querySelector('shades-command-palette-input') as HTMLElement
|
|
261
|
-
const computedStyle = window.getComputedStyle(component)
|
|
262
|
-
expect(computedStyle.overflow).toBe('hidden')
|
|
263
|
-
})
|
|
264
|
-
})
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
it('should use cubic-bezier easing for animations', async () => {
|
|
157
|
+
it('should preserve input value when opening', async () => {
|
|
268
158
|
await usingAsync(new Injector(), async (injector) => {
|
|
269
159
|
await usingAsync(createManager(), async (manager) => {
|
|
270
160
|
manager.isOpened.setValue(false)
|
|
@@ -277,47 +167,15 @@ describe('CommandPaletteInput', () => {
|
|
|
277
167
|
})
|
|
278
168
|
|
|
279
169
|
await flushUpdates()
|
|
280
|
-
animateCalls = []
|
|
281
170
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const widthAnimation = animateCalls.find(
|
|
286
|
-
(call) => Array.isArray(call.keyframes) && call.keyframes.some((kf: Keyframe) => 'width' in kf),
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
expect(widthAnimation).toBeDefined()
|
|
290
|
-
expect((widthAnimation?.options as KeyframeAnimationOptions)?.easing).toBe(
|
|
291
|
-
'cubic-bezier(0.595, 0.425, 0.415, 0.845)',
|
|
292
|
-
)
|
|
293
|
-
})
|
|
294
|
-
})
|
|
295
|
-
})
|
|
296
|
-
|
|
297
|
-
it('should fill animation forwards', async () => {
|
|
298
|
-
await usingAsync(new Injector(), async (injector) => {
|
|
299
|
-
await usingAsync(createManager(), async (manager) => {
|
|
300
|
-
manager.isOpened.setValue(false)
|
|
301
|
-
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
302
|
-
|
|
303
|
-
initializeShadeRoot({
|
|
304
|
-
injector,
|
|
305
|
-
rootElement,
|
|
306
|
-
jsxElement: <CommandPaletteInput manager={manager} />,
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
await flushUpdates()
|
|
310
|
-
animateCalls = []
|
|
171
|
+
const component = document.querySelector('shades-command-palette-input') as HTMLElement
|
|
172
|
+
const inputElement = component?.querySelector('input') as HTMLInputElement
|
|
173
|
+
inputElement.value = 'some text'
|
|
311
174
|
|
|
312
175
|
manager.isOpened.setValue(true)
|
|
313
176
|
await flushUpdates()
|
|
314
177
|
|
|
315
|
-
|
|
316
|
-
(call) => Array.isArray(call.keyframes) && call.keyframes.some((kf: Keyframe) => 'width' in kf),
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
expect(widthAnimation).toBeDefined()
|
|
320
|
-
expect((widthAnimation?.options as KeyframeAnimationOptions)?.fill).toBe('forwards')
|
|
178
|
+
expect(inputElement.value).toBe('some text')
|
|
321
179
|
})
|
|
322
180
|
})
|
|
323
181
|
})
|
|
@@ -1,45 +1,13 @@
|
|
|
1
|
-
import type { RefObject } from '@furystack/shades'
|
|
2
1
|
import { Shade, createComponent } from '@furystack/shades'
|
|
3
2
|
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
4
|
-
import { promisifyAnimation } from '../../utils/promisify-animation.js'
|
|
5
3
|
import type { CommandPaletteManager } from './command-palette-manager.js'
|
|
6
4
|
|
|
7
|
-
const animateOpenState = async (
|
|
8
|
-
wrapperRef: RefObject<HTMLDivElement>,
|
|
9
|
-
inputRef: RefObject<HTMLInputElement>,
|
|
10
|
-
isOpened: boolean,
|
|
11
|
-
) => {
|
|
12
|
-
const wrapper = wrapperRef.current
|
|
13
|
-
const input = inputRef.current
|
|
14
|
-
if (wrapper && input) {
|
|
15
|
-
if (isOpened) {
|
|
16
|
-
input.value = ''
|
|
17
|
-
await promisifyAnimation(wrapper, [{ width: '0%' }, { width: '100%' }], {
|
|
18
|
-
duration: 300,
|
|
19
|
-
fill: 'forwards',
|
|
20
|
-
easing: 'cubic-bezier(0.595, 0.425, 0.415, 0.845)',
|
|
21
|
-
})
|
|
22
|
-
input.focus()
|
|
23
|
-
} else {
|
|
24
|
-
await promisifyAnimation(wrapper, [{ width: '100%' }, { width: '0%' }], {
|
|
25
|
-
duration: 300,
|
|
26
|
-
fill: 'forwards',
|
|
27
|
-
easing: 'cubic-bezier(0.595, 0.425, 0.415, 0.845)',
|
|
28
|
-
})
|
|
29
|
-
input.value = ''
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
5
|
export const CommandPaletteInput = Shade<{ manager: CommandPaletteManager }>({
|
|
35
6
|
shadowDomName: 'shades-command-palette-input',
|
|
36
7
|
css: {
|
|
37
|
-
width: '
|
|
8
|
+
width: '100%',
|
|
38
9
|
fontFamily: cssVariableTheme.typography.fontFamily,
|
|
39
10
|
overflow: 'hidden',
|
|
40
|
-
'&[data-opened]': {
|
|
41
|
-
width: '100%',
|
|
42
|
-
},
|
|
43
11
|
'& input': {
|
|
44
12
|
color: cssVariableTheme.text.primary,
|
|
45
13
|
outline: 'none',
|
|
@@ -53,20 +21,20 @@ export const CommandPaletteInput = Shade<{ manager: CommandPaletteManager }>({
|
|
|
53
21
|
letterSpacing: '0.01em',
|
|
54
22
|
},
|
|
55
23
|
},
|
|
56
|
-
render: ({ props, useObservable, useRef
|
|
57
|
-
const { manager } = props
|
|
58
|
-
const wrapperRef = useRef<HTMLDivElement>('wrapper')
|
|
24
|
+
render: ({ props, useObservable, useRef }) => {
|
|
59
25
|
const inputRef = useRef<HTMLInputElement>('input')
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
26
|
+
useObservable('isOpened', props.manager.isOpened, {
|
|
27
|
+
onChange: (isOpened) => {
|
|
28
|
+
if (inputRef.current) {
|
|
29
|
+
if (isOpened) {
|
|
30
|
+
inputRef.current.focus()
|
|
31
|
+
} else {
|
|
32
|
+
inputRef.current.value = ''
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
63
36
|
})
|
|
64
|
-
useHostProps({ ...(isCurrentlyOpened ? { 'data-opened': '' } : {}) })
|
|
65
37
|
|
|
66
|
-
return
|
|
67
|
-
<div ref={wrapperRef} style={{ width: isCurrentlyOpened ? '100%' : '0%', overflow: 'hidden' }}>
|
|
68
|
-
<input ref={inputRef} autofocus placeholder="Type to search commands..." />
|
|
69
|
-
</div>
|
|
70
|
-
)
|
|
38
|
+
return <input ref={inputRef} autofocus placeholder="Type to search commands..." />
|
|
71
39
|
},
|
|
72
40
|
})
|