@furystack/shades-common-components 12.0.1 → 12.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +26 -0
  3. package/esm/components/avatar.d.ts.map +1 -1
  4. package/esm/components/avatar.js +3 -1
  5. package/esm/components/avatar.js.map +1 -1
  6. package/esm/components/avatar.spec.js +4 -4
  7. package/esm/components/avatar.spec.js.map +1 -1
  8. package/esm/components/cache-view.d.ts +46 -0
  9. package/esm/components/cache-view.d.ts.map +1 -0
  10. package/esm/components/cache-view.js +65 -0
  11. package/esm/components/cache-view.js.map +1 -0
  12. package/esm/components/cache-view.spec.d.ts +2 -0
  13. package/esm/components/cache-view.spec.d.ts.map +1 -0
  14. package/esm/components/cache-view.spec.js +183 -0
  15. package/esm/components/cache-view.spec.js.map +1 -0
  16. package/esm/components/icons/icon-definitions.d.ts +82 -0
  17. package/esm/components/icons/icon-definitions.d.ts.map +1 -1
  18. package/esm/components/icons/icon-definitions.js +717 -0
  19. package/esm/components/icons/icon-definitions.js.map +1 -1
  20. package/esm/components/icons/icon-definitions.spec.js +22 -2
  21. package/esm/components/icons/icon-definitions.spec.js.map +1 -1
  22. package/esm/components/icons/icon-types.d.ts +10 -0
  23. package/esm/components/icons/icon-types.d.ts.map +1 -1
  24. package/esm/components/icons/index.d.ts +1 -1
  25. package/esm/components/icons/index.d.ts.map +1 -1
  26. package/esm/components/index.d.ts +1 -0
  27. package/esm/components/index.d.ts.map +1 -1
  28. package/esm/components/index.js +1 -0
  29. package/esm/components/index.js.map +1 -1
  30. package/esm/components/page-container/index.d.ts +1 -1
  31. package/esm/components/page-container/index.js +1 -1
  32. package/esm/components/page-container/page-header.d.ts +5 -5
  33. package/esm/components/page-container/page-header.d.ts.map +1 -1
  34. package/esm/components/page-container/page-header.js +3 -3
  35. package/esm/components/skeleton.d.ts.map +1 -1
  36. package/esm/components/skeleton.js +2 -11
  37. package/esm/components/skeleton.js.map +1 -1
  38. package/esm/components/skeleton.spec.js +6 -55
  39. package/esm/components/skeleton.spec.js.map +1 -1
  40. package/esm/components/suggest/index.d.ts +1 -1
  41. package/esm/components/suggest/index.d.ts.map +1 -1
  42. package/package.json +4 -3
  43. package/src/components/avatar.spec.tsx +4 -4
  44. package/src/components/avatar.tsx +3 -1
  45. package/src/components/cache-view.spec.tsx +210 -0
  46. package/src/components/cache-view.tsx +103 -0
  47. package/src/components/icons/icon-definitions.spec.ts +28 -2
  48. package/src/components/icons/icon-definitions.ts +759 -0
  49. package/src/components/icons/icon-types.ts +12 -0
  50. package/src/components/icons/index.ts +1 -1
  51. package/src/components/index.ts +1 -0
  52. package/src/components/page-container/index.tsx +1 -1
  53. package/src/components/page-container/page-header.tsx +5 -5
  54. package/src/components/skeleton.spec.tsx +6 -73
  55. package/src/components/skeleton.tsx +2 -11
  56. package/src/components/suggest/index.tsx +1 -1
@@ -8,6 +8,9 @@ export type IconPath = {
8
8
  fillRule?: 'evenodd' | 'nonzero'
9
9
  }
10
10
 
11
+ /** Category for grouping icons in galleries */
12
+ export type IconCategory = 'Actions' | 'Navigation' | 'Status' | 'Content' | 'UI' | 'Common'
13
+
11
14
  /**
12
15
  * Defines an icon as a set of SVG paths with rendering metadata.
13
16
  * Icons are lightweight objects containing only path data -- no embedded SVG markup.
@@ -45,4 +48,13 @@ export type IconDefinition = {
45
48
  * @default 2
46
49
  */
47
50
  strokeWidth?: number
51
+
52
+ /** Human-readable display name (e.g., "Check Circle", "Arrow Left") */
53
+ name?: string
54
+ /** Short description of the icon's intended use */
55
+ description?: string
56
+ /** Search keywords for filtering (e.g., ['dismiss', 'cancel', 'x'] for close) */
57
+ keywords?: string[]
58
+ /** Category for grouping in galleries */
59
+ category?: IconCategory
48
60
  }
@@ -1,4 +1,4 @@
1
- export type { IconDefinition, IconPath } from './icon-types.js'
1
+ export type { IconCategory, IconDefinition, IconPath } from './icon-types.js'
2
2
  export { Icon } from './icon.js'
3
3
  export type { IconProps } from './icon.js'
4
4
  export * as icons from './icon-definitions.js'
@@ -8,6 +8,7 @@ export * from './badge.js'
8
8
  export * from './breadcrumb.js'
9
9
  export * from './button-group.js'
10
10
  export * from './button.js'
11
+ export * from './cache-view.js'
11
12
  export * from './card.js'
12
13
  export * from './carousel.js'
13
14
  export * from './chip.js'
@@ -30,7 +30,7 @@ export type PageContainerProps = {
30
30
  * ```tsx
31
31
  * <PageContainer maxWidth="800px" centered padding="48px" gap="24px">
32
32
  * <PageHeader
33
- * icon="👥"
33
+ * icon={<Icon icon={icons.users} />}
34
34
  * title="Users"
35
35
  * description="Manage user accounts and their roles."
36
36
  * />
@@ -6,8 +6,8 @@ import { Paper } from '../paper.js'
6
6
  * Props for the PageHeader component.
7
7
  */
8
8
  export type PageHeaderProps = {
9
- /** Optional icon (emoji or single character) displayed before the title */
10
- icon?: string
9
+ /** Optional icon displayed before the title (string or JSX element such as an Icon component) */
10
+ icon?: JSX.Element | string
11
11
  /** The page title */
12
12
  title: string
13
13
  /** Optional description text displayed below the title */
@@ -27,9 +27,9 @@ export type PageHeaderProps = {
27
27
  *
28
28
  * @example
29
29
  * ```tsx
30
- * // Simple header with icon and description
30
+ * // Header with an Icon component
31
31
  * <PageHeader
32
- * icon="👥"
32
+ * icon={<Icon icon={icons.users} />}
33
33
  * title="Users"
34
34
  * description="Manage user accounts and their roles."
35
35
  * />
@@ -39,7 +39,7 @@ export type PageHeaderProps = {
39
39
  * ```tsx
40
40
  * // Header with action buttons
41
41
  * <PageHeader
42
- * icon="📁"
42
+ * icon={<Icon icon={icons.folder} />}
43
43
  * title="Projects"
44
44
  * description="View and manage your projects."
45
45
  * actions={
@@ -46,7 +46,7 @@ describe('Skeleton', () => {
46
46
  vi.restoreAllMocks()
47
47
  })
48
48
 
49
- it('should render with shadow DOM', async () => {
49
+ it('should render with correct initial state and default delay', async () => {
50
50
  await usingAsync(new Injector(), async (injector) => {
51
51
  const rootElement = document.getElementById('root') as HTMLDivElement
52
52
 
@@ -60,40 +60,13 @@ describe('Skeleton', () => {
60
60
 
61
61
  const skeleton = document.querySelector('shade-skeleton')
62
62
  expect(skeleton).not.toBeNull()
63
- })
64
- })
65
-
66
- it('should have initial opacity of 0', async () => {
67
- await usingAsync(new Injector(), async (injector) => {
68
- const rootElement = document.getElementById('root') as HTMLDivElement
69
-
70
- initializeShadeRoot({
71
- injector,
72
- rootElement,
73
- jsxElement: <Skeleton />,
74
- })
75
-
76
- await sleepAsync(50)
77
63
 
78
- const skeleton = document.querySelector('shade-skeleton') as HTMLElement
79
- expect(skeleton).not.toBeNull()
64
+ const skeletonDiv = document.querySelector('shade-skeleton div') as HTMLElement
65
+ expect(skeletonDiv).not.toBeNull()
80
66
 
81
- const computedStyle = window.getComputedStyle(skeleton)
67
+ const computedStyle = window.getComputedStyle(skeletonDiv)
82
68
  expect(computedStyle.opacity).toBe('0')
83
- })
84
- })
85
-
86
- it('should use default delay of 1500ms', async () => {
87
- await usingAsync(new Injector(), async (injector) => {
88
- const rootElement = document.getElementById('root') as HTMLDivElement
89
-
90
- initializeShadeRoot({
91
- injector,
92
- rootElement,
93
- jsxElement: <Skeleton />,
94
- })
95
-
96
- await sleepAsync(50)
69
+ expect(computedStyle.display).toBe('inline-block')
97
70
 
98
71
  const fadeInCall = animateCalls.find(
99
72
  (call) => Array.isArray(call.keyframes) && call.keyframes.some((kf: Keyframe) => 'opacity' in kf),
@@ -125,26 +98,6 @@ describe('Skeleton', () => {
125
98
  })
126
99
  })
127
100
 
128
- it('should have correct css styles applied', async () => {
129
- await usingAsync(new Injector(), async (injector) => {
130
- const rootElement = document.getElementById('root') as HTMLDivElement
131
-
132
- initializeShadeRoot({
133
- injector,
134
- rootElement,
135
- jsxElement: <Skeleton />,
136
- })
137
-
138
- await sleepAsync(50)
139
-
140
- const skeleton = document.querySelector('shade-skeleton') as HTMLElement
141
- expect(skeleton).not.toBeNull()
142
-
143
- const computedStyle = window.getComputedStyle(skeleton)
144
- expect(computedStyle.display).toBe('inline-block')
145
- })
146
- })
147
-
148
101
  it('should start fade-in animation with correct parameters', async () => {
149
102
  await usingAsync(new Injector(), async (injector) => {
150
103
  const rootElement = document.getElementById('root') as HTMLDivElement
@@ -175,7 +128,7 @@ describe('Skeleton', () => {
175
128
  })
176
129
  })
177
130
 
178
- it('should start background animation after fade-in completes', async () => {
131
+ it('should start background animation with correct keyframes after fade-in completes', async () => {
179
132
  await usingAsync(new Injector(), async (injector) => {
180
133
  const rootElement = document.getElementById('root') as HTMLDivElement
181
134
 
@@ -196,26 +149,6 @@ describe('Skeleton', () => {
196
149
  const options = backgroundAnimation?.options as KeyframeAnimationOptions
197
150
  expect(options.duration).toBe(10000)
198
151
  expect(options.iterations).toBe(Infinity)
199
- })
200
- })
201
-
202
- it('should have gradient background animation keyframes', async () => {
203
- await usingAsync(new Injector(), async (injector) => {
204
- const rootElement = document.getElementById('root') as HTMLDivElement
205
-
206
- initializeShadeRoot({
207
- injector,
208
- rootElement,
209
- jsxElement: <Skeleton delay={0} />,
210
- })
211
-
212
- await sleepAsync(100)
213
-
214
- const backgroundAnimation = animateCalls.find(
215
- (call) => Array.isArray(call.keyframes) && call.keyframes.some((kf: Keyframe) => 'backgroundPosition' in kf),
216
- )
217
-
218
- expect(backgroundAnimation).toBeDefined()
219
152
 
220
153
  const keyframes = backgroundAnimation?.keyframes as Keyframe[]
221
154
  expect(keyframes).toHaveLength(3)
@@ -11,15 +11,6 @@ export type SkeletonProps = {
11
11
 
12
12
  export const Skeleton = Shade<SkeletonProps>({
13
13
  shadowDomName: 'shade-skeleton',
14
- css: {
15
- opacity: '0',
16
- display: 'inline-block',
17
- background: `linear-gradient(-45deg, color-mix(in srgb, ${cssVariableTheme.text.secondary} 10%, transparent), color-mix(in srgb, ${cssVariableTheme.text.secondary} 30%, transparent), color-mix(in srgb, ${cssVariableTheme.text.secondary} 10%, transparent))`,
18
- backgroundSize: '400% 400%',
19
- width: '100%',
20
- height: '100%',
21
- minHeight: '1em',
22
- },
23
14
  render: ({ props, useRef }) => {
24
15
  const wrapperRef = useRef<HTMLDivElement>('wrapper')
25
16
  const { delay = 1500 } = props
@@ -49,8 +40,8 @@ export const Skeleton = Shade<SkeletonProps>({
49
40
  style={{
50
41
  opacity: '0',
51
42
  display: 'inline-block',
52
- background: 'inherit',
53
- backgroundSize: 'inherit',
43
+ background: `linear-gradient(-45deg, color-mix(in srgb, ${cssVariableTheme.text.secondary} 10%, transparent), color-mix(in srgb, ${cssVariableTheme.text.secondary} 30%, transparent), color-mix(in srgb, ${cssVariableTheme.text.secondary} 10%, transparent))`,
44
+ backgroundSize: '400% 400%',
54
45
  width: '100%',
55
46
  height: '100%',
56
47
  minHeight: '1em',
@@ -16,7 +16,7 @@ export * from './suggestion-list.js'
16
16
  export * from './suggestion-result.js'
17
17
 
18
18
  export interface SuggestProps<T> {
19
- defaultPrefix: string
19
+ defaultPrefix: JSX.Element | string
20
20
  getEntries: (term: string) => Promise<T[]>
21
21
  getSuggestionEntry: (entry: T) => SuggestionResult
22
22
  onSelectSuggestion: (entry: T) => void