@payfit/unity-illustrations 2.55.21 → 2.55.23

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 (38) hide show
  1. package/package.json +18 -11
  2. package/skills/unity-illustrations/SKILL.md +39 -0
  3. package/src/agent-references/illustrations-catalog.json +1996 -0
  4. package/src/agent-references/manifest.json +16 -0
  5. package/dist/esm/scripts/agent-references/illustration-reference.d.ts +0 -17
  6. package/src/agent-references/README.mdx +0 -17
  7. package/src/agent-references/illustrations.mdx +0 -74
  8. package/src/components/illustration/Illustration.stories.tsx +0 -362
  9. package/src/components/illustration/Illustration.tsx +0 -169
  10. package/src/components/illustration/figma/IllustrationLarge.figma.ts +0 -258
  11. package/src/components/illustration/figma/IllustrationMedium.figma.ts +0 -258
  12. package/src/components/illustration/figma/IllustrationSmall.figma.ts +0 -258
  13. package/src/components/lazy-illustration/LazyIllustration.stories.tsx +0 -204
  14. package/src/components/lazy-illustration/LazyIllustration.tsx +0 -125
  15. package/src/components/lazy-illustration/figma/LazyIllustrationLarge.figma.ts +0 -255
  16. package/src/components/lazy-illustration/figma/LazyIllustrationMedium.figma.ts +0 -255
  17. package/src/components/lazy-illustration/figma/LazyIllustrationSmall.figma.ts +0 -255
  18. package/src/docs/1-Introduction/1-Welcome.mdx +0 -111
  19. package/src/docs/1-Introduction/2-Getting Started.mdx +0 -25
  20. package/src/docs/1-Introduction/3-Usage.mdx +0 -114
  21. package/src/docs/1-Introduction/4-Changelog.mdx +0 -6
  22. package/src/docs/2-Reference/1-Find my illustration.mdx +0 -12
  23. package/src/docs/2-Reference/2-Find my animation.mdx +0 -14
  24. package/src/docs/2-Reference/3-Multi brand support.mdx +0 -146
  25. package/src/docs/blocks/AnimationLibrary.tsx +0 -181
  26. package/src/docs/blocks/BrandSupportBadge.tsx +0 -190
  27. package/src/docs/blocks/BrandSupportFilter.tsx +0 -72
  28. package/src/docs/blocks/Cards.tsx +0 -74
  29. package/src/docs/blocks/IllustrationLibrary.tsx +0 -179
  30. package/src/docs/blocks/useStorybookTheme.ts +0 -73
  31. package/src/index.ts +0 -4
  32. package/src/scripts/agent-references/illustration-reference.test.ts +0 -100
  33. package/src/scripts/agent-references/illustration-reference.ts +0 -140
  34. package/src/scripts/generate-assets.ts +0 -649
  35. package/src/scripts/templates/assetTemplate.ts +0 -224
  36. package/src/scripts/templates/baseTypes.ts +0 -45
  37. package/src/scripts/templates/indexTemplate.ts +0 -109
  38. package/src/unity.css +0 -5
@@ -1,179 +0,0 @@
1
- import React, { memo, useCallback, useMemo, useState } from 'react'
2
-
3
- import { UnityThemeProvider } from '@payfit/unity-themes'
4
-
5
- import { LazyIllustration } from '../../components/lazy-illustration/LazyIllustration'
6
- import type { UnityIllustrationName } from '../../generated/illustrationAssets'
7
-
8
- import { illustrationNames } from '../../generated/illustrationAssets'
9
- import type { BrandSupportFilter } from './BrandSupportFilter'
10
-
11
- import {
12
- BrandSupportBadge,
13
- useBrandSupportRecords,
14
- } from './BrandSupportBadge'
15
- import {
16
- BrandSupportFilterControl,
17
- matchesBrandSupportFilter,
18
- } from './BrandSupportFilter'
19
- import { useStorybookTheme } from './useStorybookTheme'
20
-
21
- const debounce = <P = unknown,>(
22
- callback: (...args: P[]) => unknown,
23
- wait: number,
24
- ) => {
25
- let timeoutId: number
26
- return (...args: P[]) => {
27
- if (timeoutId) {
28
- window.clearTimeout(timeoutId)
29
- }
30
- timeoutId = window.setTimeout(() => {
31
- callback(...args)
32
- }, wait)
33
- }
34
- }
35
-
36
- const IllustrationItem = memo(
37
- ({
38
- children,
39
- name,
40
- copyText,
41
- onClick,
42
- }: React.PropsWithChildren<{
43
- name: UnityIllustrationName
44
- copyText: string
45
- onClick: () => void
46
- }>) => {
47
- return (
48
- <li>
49
- <button
50
- onClick={onClick}
51
- className="uy:group uy:flex uy:h-full uy:w-full uy:flex-col uy:gap-150 uy:p-200 uy:transition-all uy:rounded-lg uy:bg-surface-neutral uy:shadow-raising uy:hover:shadow-flying uy:focus-visible:shadow-floating uy:focus-visible:outline-none uy:focus-visible:ring-2 uy:focus-visible:ring-ring uy:focus-visible:ring-offset-2 uy:focus-visible:ring-utility-focus-ring uy:focus-visible:border-border-form-hover uy:focus-visible:bg-surface-neutral-low-hover uy:border uy:border-solid uy:border-border-neutral"
52
- >
53
- <figure className="uy:flex uy:h-full uy:w-full uy:flex-col uy:items-center uy:gap-150">
54
- <figcaption className="uy:w-full uy:text-left">
55
- <span className="uy:block uy:w-full uy:truncate uy:font-mono uy:text-50 uy:leading-normal uy:text-content-neutral">
56
- {name}
57
- </span>
58
- </figcaption>
59
- <div className="uy:flex uy:py-200 uy:w-[90%] uy:items-center uy:justify-center uy:transition-all uy:group-hover:scale-110">
60
- {children}
61
- </div>
62
- <div className="uy:mt-auto uy:flex uy:w-full uy:items-center uy:justify-between uy:gap-100">
63
- <BrandSupportBadge name={name} />
64
- <span className="uy:typography-action-small uy:bg-transparent uy:theme-legacy:text-content-primary uy:theme-rebrand:text-content-neutral uy:theme-rebrand:underline uy:whitespace-nowrap">
65
- {copyText}
66
- </span>
67
- </div>
68
- </figure>
69
- </button>
70
- </li>
71
- )
72
- },
73
- )
74
-
75
- const IllustrationLibrary = ({
76
- filter,
77
- }: {
78
- filter?: 'filled' | 'outlined'
79
- }) => {
80
- const theme = useStorybookTheme()
81
- const [query, setQuery] = useState<string>('')
82
- const [copiedIllustration, setCopiedIllustration] = useState<string | null>(
83
- null,
84
- )
85
- const [brandFilter, setBrandFilter] = useState<BrandSupportFilter>('all')
86
-
87
- const illustrationList = useMemo(() => {
88
- const predicate =
89
- filter !== undefined
90
- ? (name: string) => name.toLowerCase().includes(filter)
91
- : () => true
92
- return illustrationNames
93
- .filter(name => !name.endsWith('Animation'))
94
- .filter(name => predicate(name))
95
- }, [filter])
96
- const brandSupportByName = useBrandSupportRecords(illustrationList)
97
-
98
- const copyToClipboard = useCallback((illustrationName: string) => {
99
- const importStatement = `import ${illustrationName} from '@payfit/unity-illustrations/assets/${illustrationName}'`
100
-
101
- navigator.clipboard
102
- .writeText(importStatement)
103
- .then(() => {
104
- setCopiedIllustration(illustrationName)
105
- setTimeout(() => {
106
- setCopiedIllustration(null)
107
- }, 5000)
108
- })
109
- .catch((error: unknown) => {
110
- console.error('Failed to copy: ', error)
111
- })
112
- }, [])
113
-
114
- const updateSearchQuery = debounce((illustrationName: string) => {
115
- setQuery(illustrationName)
116
- }, 150)
117
-
118
- const illustrationListMatchingSearch = illustrationList.filter(
119
- illustrationName =>
120
- illustrationName.toLowerCase().includes(query.toLowerCase()) &&
121
- matchesBrandSupportFilter(
122
- brandSupportByName.get(illustrationName) ?? 'loading',
123
- brandFilter,
124
- ),
125
- )
126
-
127
- return (
128
- <UnityThemeProvider key={theme} theme={theme}>
129
- <section className="uy:flex uy:flex-col uy:gap-300 uy:max-w-[80vmax] uy:mx-auto">
130
- <header>
131
- <h3>Illustration Gallery</h3>
132
- <p className="uy:m-0!">
133
- Click on any illustration to copy its import path to the clipboard.
134
- </p>
135
- </header>
136
- <div className="uy:flex uy:flex-col uy:gap-150">
137
- <BrandSupportFilterControl
138
- name="illustration-brand-support-filter"
139
- value={brandFilter}
140
- onChange={setBrandFilter}
141
- />
142
- <input
143
- type="search"
144
- placeholder="Search for an illustration..."
145
- className="uy:flex uy:h-500 uy:w-full uy:text-content-form-enabled uy:rounded-100 uy:border uy:border-solid uy:border-border-form-enabled uy:bg-background uy:px-150 uy:py-100 uy:typography-body uy:placeholder:text-content-neutral-lowest uy:hover:border-border-form-hover uy:focus-visible:outline-none uy:focus-visible:ring-2 uy:focus-visible:ring-ring uy:focus-visible:ring-offset-2 uy:focus-visible:ring-utility-focus-ring"
146
- onChange={e => {
147
- updateSearchQuery(e.target.value)
148
- }}
149
- />
150
- </div>
151
- <ul className="sb-unstyled uy:list-none uy:grid uy:grid-cols-[repeat(auto-fill,minmax(200px,_1fr))] uy:gap-x-100 uy:gap-y-200">
152
- {illustrationListMatchingSearch.map(name => {
153
- return (
154
- <IllustrationItem
155
- name={name}
156
- copyText={
157
- copiedIllustration === name ? 'Copied!' : 'Click to Copy'
158
- }
159
- key={name}
160
- onClick={() => {
161
- copyToClipboard(name)
162
- }}
163
- >
164
- <LazyIllustration
165
- variant="picture"
166
- alt={`${name} illustration`}
167
- name={name}
168
- className="uy:h-[160px]"
169
- />
170
- </IllustrationItem>
171
- )
172
- })}
173
- </ul>
174
- </section>
175
- </UnityThemeProvider>
176
- )
177
- }
178
-
179
- export default IllustrationLibrary
@@ -1,73 +0,0 @@
1
- import { useSyncExternalStore } from 'react'
2
-
3
- import type { UnityTheme } from '@payfit/unity-themes'
4
-
5
- import { addons } from 'storybook/preview-api'
6
-
7
- const defaultTheme: UnityTheme = 'legacy'
8
- const globalsUpdatedEvent = 'globalsUpdated'
9
- let currentTheme: UnityTheme = defaultTheme
10
-
11
- function normalizeTheme(theme: unknown): UnityTheme {
12
- return theme === 'rebrand' ? 'rebrand' : defaultTheme
13
- }
14
-
15
- function readThemeFromDocument(): UnityTheme {
16
- if (typeof document === 'undefined') {
17
- return defaultTheme
18
- }
19
-
20
- return document.documentElement.getAttribute('data-uy-theme') === 'rebrand'
21
- ? 'rebrand'
22
- : defaultTheme
23
- }
24
-
25
- function subscribeToThemeChange(onStoreChange: () => void) {
26
- const channel = addons.getChannel()
27
-
28
- currentTheme = readThemeFromDocument()
29
-
30
- const handleStoreChange = (theme: UnityTheme) => {
31
- if (currentTheme === theme) {
32
- return
33
- }
34
-
35
- currentTheme = theme
36
- onStoreChange()
37
- }
38
-
39
- const handleGlobalsUpdated = ({
40
- globals,
41
- }: {
42
- globals?: Record<string, unknown>
43
- }) => {
44
- handleStoreChange(normalizeTheme(globals?.theme))
45
- }
46
-
47
- channel.on(globalsUpdatedEvent, handleGlobalsUpdated)
48
-
49
- const observer =
50
- typeof MutationObserver === 'undefined'
51
- ? undefined
52
- : new MutationObserver(() => {
53
- handleStoreChange(readThemeFromDocument())
54
- })
55
-
56
- observer?.observe(document.documentElement, {
57
- attributes: true,
58
- attributeFilter: ['data-uy-theme'],
59
- })
60
-
61
- return () => {
62
- channel.off(globalsUpdatedEvent, handleGlobalsUpdated)
63
- observer?.disconnect()
64
- }
65
- }
66
-
67
- export function useStorybookTheme(): UnityTheme {
68
- return useSyncExternalStore(
69
- subscribeToThemeChange,
70
- () => currentTheme,
71
- () => defaultTheme,
72
- )
73
- }
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './components/illustration/Illustration'
2
- export * from './components/lazy-illustration/LazyIllustration'
3
-
4
- export * from './generated/illustrationAssets'
@@ -1,100 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import {
4
- generateIllustrationsReference,
5
- getIllustrationReferenceGroups,
6
- } from './illustration-reference.js'
7
-
8
- describe('illustration agent references', () => {
9
- it('groups illustrations by category with stable name sorting', () => {
10
- expect(
11
- getIllustrationReferenceGroups([
12
- {
13
- name: 'WriteBook',
14
- type: 'svg',
15
- animated: false,
16
- category: 'picture',
17
- },
18
- {
19
- name: 'FAQAnimation',
20
- type: 'image',
21
- animated: true,
22
- category: 'animation',
23
- },
24
- {
25
- name: 'Accounting',
26
- type: 'svg',
27
- animated: false,
28
- category: 'picture',
29
- },
30
- { name: 'Baby', type: 'svg', animated: false, category: 'icon' },
31
- ]),
32
- ).toEqual([
33
- {
34
- category: 'icon',
35
- title: 'Illustrated icons',
36
- components: [
37
- { name: 'Baby', type: 'svg', animated: false, category: 'icon' },
38
- ],
39
- },
40
- {
41
- category: 'picture',
42
- title: 'Illustrated pictures',
43
- components: [
44
- {
45
- name: 'Accounting',
46
- type: 'svg',
47
- animated: false,
48
- category: 'picture',
49
- },
50
- {
51
- name: 'WriteBook',
52
- type: 'svg',
53
- animated: false,
54
- category: 'picture',
55
- },
56
- ],
57
- },
58
- {
59
- category: 'animation',
60
- title: 'Animations',
61
- components: [
62
- {
63
- name: 'FAQAnimation',
64
- type: 'image',
65
- animated: true,
66
- category: 'animation',
67
- },
68
- ],
69
- },
70
- ])
71
- })
72
-
73
- it('generates a compact Storybook MDX list with lazy and eager usage', () => {
74
- const markdown = generateIllustrationsReference([
75
- {
76
- name: 'FAQAnimation',
77
- type: 'image',
78
- animated: true,
79
- category: 'animation',
80
- },
81
- ])
82
-
83
- expect(markdown).toContain('{/* AUTO-GENERATED FILE. DO NOT EDIT.')
84
- expect(markdown).toContain(
85
- '<Meta title="Agent References/Illustrations" />',
86
- )
87
- expect(markdown).toContain('## Animations (picture; animated)')
88
- expect(markdown).not.toContain('| Name | Variant | Type | Animated |')
89
- expect(markdown).toContain('- FAQAnimation')
90
- expect(markdown).toContain(
91
- 'Lazy: `<LazyIllustration name="ExactName" variant="icon|picture" alt="..." />`',
92
- )
93
- expect(markdown).toContain(
94
- 'Eager: `import Asset from "@payfit/unity-illustrations/ExactName"`',
95
- )
96
- expect(markdown).not.toContain(
97
- '`<LazyIllustration name="FAQAnimation" variant="picture" />`',
98
- )
99
- })
100
- })
@@ -1,140 +0,0 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
-
4
- export type IllustrationReferenceComponent = {
5
- name: string
6
- type: string
7
- animated: boolean
8
- category?: string
9
- }
10
-
11
- const GENERATED_NOTICE = `{/* AUTO-GENERATED FILE. DO NOT EDIT.
12
- Generated by unity-illustrations:pre-build.
13
- Source: Unity illustration asset metadata.
14
- */}\n`
15
-
16
- const STORYBOOK_META = `import { Meta } from '@storybook/addon-docs/blocks'\n\n<Meta title="Agent References/Illustrations" />\n`
17
- const README_STORYBOOK_META = `import { Meta } from '@storybook/addon-docs/blocks'\n\n<Meta title="Agent References/Illustrations Overview" />\n`
18
-
19
- const CATEGORY_ORDER = ['icon', 'picture', 'animation', 'other']
20
-
21
- const CATEGORY_TITLES: Record<string, string> = {
22
- icon: 'Illustrated icons',
23
- picture: 'Illustrated pictures',
24
- animation: 'Animations',
25
- other: 'Other illustrations',
26
- }
27
-
28
- const getCategory = (component: IllustrationReferenceComponent) =>
29
- component.category ?? 'other'
30
-
31
- const chunk = <T>(items: T[], size: number) => {
32
- const chunks: T[][] = []
33
-
34
- for (let index = 0; index < items.length; index += size) {
35
- chunks.push(items.slice(index, index + size))
36
- }
37
-
38
- return chunks
39
- }
40
-
41
- export const getIllustrationReferenceGroups = (
42
- components: IllustrationReferenceComponent[],
43
- ) => {
44
- const knownCategories = new Set(CATEGORY_ORDER)
45
- const categories = [
46
- ...CATEGORY_ORDER,
47
- ...Array.from(new Set(components.map(getCategory))).filter(
48
- category => !knownCategories.has(category),
49
- ),
50
- ]
51
-
52
- return categories
53
- .map(category => ({
54
- category,
55
- title: CATEGORY_TITLES[category] ?? category,
56
- components: components
57
- .filter(component => getCategory(component) === category)
58
- .slice()
59
- .sort((a, b) => a.name.localeCompare(b.name)),
60
- }))
61
- .filter(group => group.components.length > 0)
62
- }
63
-
64
- export const generateIllustrationsReference = (
65
- components: IllustrationReferenceComponent[],
66
- ) => {
67
- const lines = [
68
- STORYBOOK_META,
69
- '# Illustrations',
70
- '',
71
- GENERATED_NOTICE,
72
- '',
73
- 'Agent reference. Exact illustration names are grouped by variant to reduce context.',
74
- '',
75
- 'Lazy: `<LazyIllustration name="ExactName" variant="icon|picture" alt="..." />`.',
76
- '',
77
- 'Eager: `import Asset from "@payfit/unity-illustrations/ExactName"`, then `<Illustration src={Asset} variant="icon|picture" alt="..." />`.',
78
- '',
79
- 'Animations use `variant="picture"`.',
80
- '',
81
- ]
82
-
83
- for (const group of getIllustrationReferenceGroups(components)) {
84
- const variant = group.category === 'icon' ? 'icon' : 'picture'
85
- const animated = group.category === 'animation' ? '; animated' : ''
86
-
87
- lines.push(
88
- `## ${group.title} (${variant}${animated})`,
89
- '',
90
- ...chunk(
91
- group.components.map(component => component.name),
92
- 8,
93
- ).map(names => `- ${names.join(', ')}`),
94
- '',
95
- )
96
- }
97
-
98
- return `${lines.join('\n').trimEnd()}\n`
99
- }
100
-
101
- export const generateIllustrationsAgentReferencesReadme =
102
- () => `${README_STORYBOOK_META}
103
- # Unity Illustrations Agent References
104
-
105
- ${GENERATED_NOTICE}
106
-
107
- This directory contains generated Storybook docs references for Unity illustrations. These files are intended for Storybook MCP, MCP indexers, and AI agents.
108
-
109
- Storybook includes these MDX files through the shared \`../src/**/*.mdx\` stories glob, and \`@storybook/addon-mcp\` exposes docs content to MCP clients.
110
-
111
- - [Illustrations](./illustrations.mdx)
112
- `
113
-
114
- export const writeIllustrationAgentReferences = ({
115
- components,
116
- outputDir,
117
- }: {
118
- components: IllustrationReferenceComponent[]
119
- outputDir: string
120
- }) => {
121
- try {
122
- fs.mkdirSync(outputDir, { recursive: true })
123
- fs.writeFileSync(
124
- path.join(outputDir, 'README.mdx'),
125
- generateIllustrationsAgentReferencesReadme(),
126
- 'utf8',
127
- )
128
- fs.writeFileSync(
129
- path.join(outputDir, 'illustrations.mdx'),
130
- generateIllustrationsReference(components),
131
- 'utf8',
132
- )
133
- } catch (error) {
134
- throw new Error(
135
- `Failed to write illustration agent references to ${outputDir}: ${
136
- error instanceof Error ? error.message : String(error)
137
- }`,
138
- )
139
- }
140
- }