@antadesign/anta 0.1.1-dev.1 → 0.1.1-dev.2
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/NOTICES.md +279 -0
- package/README.md +90 -24
- package/dist/anta_global_tokens.css +329 -0
- package/dist/anta_helpers.d.ts +8 -0
- package/dist/anta_helpers.js +3 -0
- package/dist/components/Icon.d.ts +40 -0
- package/dist/components/Icon.js +18 -0
- package/dist/components/Progress.d.ts +33 -4
- package/dist/components/Progress.js +5 -0
- package/dist/components/Text.d.ts +42 -0
- package/dist/components/Text.js +22 -0
- package/dist/components/Text.module.css +6 -0
- package/dist/elements/a-icon.css +16 -0
- package/dist/elements/a-icon.d.ts +12 -0
- package/dist/elements/a-icon.js +13 -0
- package/dist/elements/a-icon.shapes.css +345 -0
- package/dist/elements/a-icon.shapes.d.ts +93 -0
- package/dist/elements/a-icon.shapes.js +179 -0
- package/dist/elements/a-progress.css +4 -4
- package/dist/elements/a-progress.d.ts +2 -1
- package/dist/elements/a-progress.js +3 -1
- package/dist/elements/a-text.css +75 -0
- package/dist/elements/a-text.d.ts +10 -0
- package/dist/elements/a-text.js +143 -0
- package/dist/elements/index.d.ts +5 -0
- package/dist/elements/index.js +14 -1
- package/dist/general_types.d.ts +74 -0
- package/dist/generate-icons.mjs +181 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +7 -0
- package/dist/jsx-runtime.d.ts +17 -1
- package/package.json +11 -4
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* generate-icons.mjs — read a folder of SVGs, emit a CSS file with one
|
|
4
|
+
* `a-icon[shape="…"]` rule per icon and a `.d.ts` file that augments
|
|
5
|
+
* Anta's `IconShapes` interface so the new shapes flow into `IconShape`.
|
|
6
|
+
*
|
|
7
|
+
* Run from CLI:
|
|
8
|
+
* node scripts/generate-icons.mjs --input <svg-folder> --output <out-folder> --name <basename>
|
|
9
|
+
*
|
|
10
|
+
* Or import programmatically:
|
|
11
|
+
* import { generate } from '@antadesign/anta/generate-icons.mjs'
|
|
12
|
+
* await generate({ input, output, name, builtInShapes })
|
|
13
|
+
*
|
|
14
|
+
* Defaults:
|
|
15
|
+
* --name = "a-icon.shapes"
|
|
16
|
+
* --output = "."
|
|
17
|
+
* --input is required
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import fs from 'node:fs'
|
|
21
|
+
import path from 'node:path'
|
|
22
|
+
import { fileURLToPath } from 'node:url'
|
|
23
|
+
|
|
24
|
+
// SVGs whose names match these get a "collision" warning so consumers
|
|
25
|
+
// know they're shadowing a built-in. Anta passes its own list when
|
|
26
|
+
// generating its own shapes; for consumers, we include the canonical
|
|
27
|
+
// built-in names so generating a same-named shape is flagged.
|
|
28
|
+
const DEFAULT_BUILT_IN = [
|
|
29
|
+
'chevron-down', 'chevron-up', 'chevron-left', 'chevron-right',
|
|
30
|
+
'check', 'x', 'info', 'warning-triangle', 'plus', 'minus', 'menu', 'copy',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
function encodeSvg(svg) {
|
|
34
|
+
return svg
|
|
35
|
+
.replace(/"/g, "'")
|
|
36
|
+
.replace(/[\r\n%#()<>?[\\\]^`{|}]/g, encodeURIComponent)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Removes `width=…` and `height=…` only from the root <svg> opening tag.
|
|
40
|
+
// Child elements (e.g. <rect width="14"…>) are intentionally untouched.
|
|
41
|
+
// Handles double-quoted, single-quoted, and unquoted attribute values.
|
|
42
|
+
function stripDimensions(svg) {
|
|
43
|
+
return svg.replace(/<svg\b[^>]*>/i, (m) =>
|
|
44
|
+
m.replace(/\s(?:width|height)\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/g, '')
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function generate({ input, output = '.', name = 'a-icon.shapes', internal = false } = {}) {
|
|
49
|
+
if (!input) throw new Error('generate-icons: --input is required')
|
|
50
|
+
const inDir = path.resolve(input)
|
|
51
|
+
const outDir = path.resolve(output)
|
|
52
|
+
if (!fs.existsSync(inDir)) throw new Error(`generate-icons: input folder not found: ${inDir}`)
|
|
53
|
+
fs.mkdirSync(outDir, { recursive: true })
|
|
54
|
+
|
|
55
|
+
const files = fs.readdirSync(inDir).filter((f) => f.endsWith('.svg')).sort()
|
|
56
|
+
if (files.length === 0) {
|
|
57
|
+
console.warn(`generate-icons: no .svg files in ${inDir}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const shapes = []
|
|
61
|
+
const cssLines = ['/* Auto-generated by scripts/generate-icons.mjs. Do not edit by hand. */', '']
|
|
62
|
+
// Built-in collision detection is for consumer runs only. Anta's own
|
|
63
|
+
// build passes --internal so it doesn't warn about every one of its
|
|
64
|
+
// own shapes "colliding" with itself.
|
|
65
|
+
const builtInSet = internal ? new Set() : new Set(DEFAULT_BUILT_IN)
|
|
66
|
+
const collisions = []
|
|
67
|
+
|
|
68
|
+
for (const file of files) {
|
|
69
|
+
const shape = path.parse(file).name
|
|
70
|
+
if (shapes.includes(shape)) {
|
|
71
|
+
console.warn(`generate-icons: duplicate shape name "${shape}" — skipping`)
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
if (builtInSet.has(shape)) collisions.push(shape)
|
|
75
|
+
const raw = fs.readFileSync(path.join(inDir, file), 'utf8')
|
|
76
|
+
const encoded = encodeSvg(stripDimensions(raw)).trim()
|
|
77
|
+
cssLines.push(`a-icon[shape="${shape}"] {`)
|
|
78
|
+
cssLines.push(` --icon: url("data:image/svg+xml,${encoded}");`)
|
|
79
|
+
cssLines.push('}')
|
|
80
|
+
cssLines.push('')
|
|
81
|
+
shapes.push(shape)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (collisions.length > 0) {
|
|
85
|
+
console.warn(
|
|
86
|
+
`generate-icons: ${collisions.length} shape name(s) collide with Anta's built-in icons: ` +
|
|
87
|
+
`${collisions.join(', ')}. ` +
|
|
88
|
+
`The runtime CSS loaded last wins; import yours after \`@antadesign/anta/elements\` to override.`
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Optional synonyms — extra search keywords per shape. Read from
|
|
93
|
+
// `<input>/synonyms.json` if present; consumers/maintainers extend
|
|
94
|
+
// the list as their icon set grows. Format: { "shape-name": ["alt", "term"] }.
|
|
95
|
+
const synFile = path.join(inDir, 'synonyms.json')
|
|
96
|
+
/** @type {Record<string, string[]>} */
|
|
97
|
+
let synonyms = {}
|
|
98
|
+
if (fs.existsSync(synFile)) {
|
|
99
|
+
try {
|
|
100
|
+
const parsed = JSON.parse(fs.readFileSync(synFile, 'utf8'))
|
|
101
|
+
for (const [shape, list] of Object.entries(parsed)) {
|
|
102
|
+
if (!shapes.includes(shape)) {
|
|
103
|
+
console.warn(`generate-icons: synonyms.json references unknown shape "${shape}" — skipping`)
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
if (!Array.isArray(list) || !list.every((v) => typeof v === 'string')) {
|
|
107
|
+
console.warn(`generate-icons: synonyms.json entry for "${shape}" is not a string array — skipping`)
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
synonyms[shape] = list
|
|
111
|
+
}
|
|
112
|
+
} catch (e) {
|
|
113
|
+
console.warn(`generate-icons: failed to parse ${synFile}: ${e.message}`)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const cssPath = path.join(outDir, `${name}.css`)
|
|
118
|
+
const tsPath = path.join(outDir, `${name}.ts`)
|
|
119
|
+
fs.writeFileSync(cssPath, cssLines.join('\n'))
|
|
120
|
+
|
|
121
|
+
const synonymsEntries = Object.entries(synonyms)
|
|
122
|
+
const tsLines = [
|
|
123
|
+
'/* Auto-generated by scripts/generate-icons.mjs. Do not edit by hand. */',
|
|
124
|
+
'',
|
|
125
|
+
'export const ICON_SHAPES = [',
|
|
126
|
+
...shapes.map((s) => ` '${s}',`),
|
|
127
|
+
"] as const",
|
|
128
|
+
'',
|
|
129
|
+
'export const ICON_SYNONYMS: Readonly<Record<string, readonly string[]>> = {',
|
|
130
|
+
...synonymsEntries.map(([shape, list]) =>
|
|
131
|
+
` '${shape}': [${list.map((v) => `'${v.replace(/'/g, "\\'")}'`).join(', ')}],`
|
|
132
|
+
),
|
|
133
|
+
'}',
|
|
134
|
+
'',
|
|
135
|
+
"declare module '@antadesign/anta' {",
|
|
136
|
+
' interface IconShapes {',
|
|
137
|
+
...shapes.map((s) => ` '${s}': true`),
|
|
138
|
+
' }',
|
|
139
|
+
'}',
|
|
140
|
+
'',
|
|
141
|
+
"export type IconShape = keyof import('@antadesign/anta').IconShapes",
|
|
142
|
+
'',
|
|
143
|
+
]
|
|
144
|
+
fs.writeFileSync(tsPath, tsLines.join('\n'))
|
|
145
|
+
|
|
146
|
+
console.log(`generate-icons: wrote ${shapes.length} shape${shapes.length === 1 ? '' : 's'} to ${cssPath} and ${tsPath}`)
|
|
147
|
+
return { shapes, cssPath, tsPath }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function parseArgs(argv) {
|
|
151
|
+
const out = {}
|
|
152
|
+
for (let i = 0; i < argv.length; i++) {
|
|
153
|
+
const arg = argv[i]
|
|
154
|
+
if (arg.startsWith('--')) {
|
|
155
|
+
const key = arg.slice(2)
|
|
156
|
+
const next = argv[i + 1]
|
|
157
|
+
if (next && !next.startsWith('--')) {
|
|
158
|
+
out[key] = next
|
|
159
|
+
i++
|
|
160
|
+
} else {
|
|
161
|
+
out[key] = true
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return out
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const isMain = import.meta.url === `file://${process.argv[1]}` ||
|
|
169
|
+
import.meta.url === fileURLToPath(import.meta.url + '')
|
|
170
|
+
if (isMain || process.argv[1]?.endsWith('generate-icons.mjs')) {
|
|
171
|
+
const args = parseArgs(process.argv.slice(2))
|
|
172
|
+
generate({
|
|
173
|
+
input: args.input,
|
|
174
|
+
output: args.output,
|
|
175
|
+
name: args.name,
|
|
176
|
+
internal: args.internal === true,
|
|
177
|
+
}).catch((e) => {
|
|
178
|
+
console.error(e.message)
|
|
179
|
+
process.exit(1)
|
|
180
|
+
})
|
|
181
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @antadesign/anta — Antithesis Design System
|
|
3
|
+
*
|
|
4
|
+
* Portable UI components with web component internals and JSX wrappers.
|
|
5
|
+
* Works with React, Preact (via compat or `configure()`), or any custom JSX runtime.
|
|
6
|
+
*
|
|
7
|
+
* Import components from this entry point:
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { Progress } from '@antadesign/anta'
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Register custom elements (client-side only):
|
|
13
|
+
* ```ts
|
|
14
|
+
* import '@antadesign/anta/elements'
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
1
19
|
export { Progress } from './components/Progress';
|
|
20
|
+
export type { ProgressProps } from './components/Progress';
|
|
21
|
+
export { Text } from './components/Text';
|
|
22
|
+
export type { TextProps } from './components/Text';
|
|
23
|
+
export { Icon } from './components/Icon';
|
|
24
|
+
export type { IconProps } from './components/Icon';
|
|
25
|
+
export { ICON_SHAPES, ICON_SYNONYMS } from './elements/a-icon.shapes';
|
|
26
|
+
export type { BaseProps, BaseAttributes } from './general_types';
|
|
2
27
|
export { configure } from './jsx-runtime';
|
|
28
|
+
/**
|
|
29
|
+
* Seed interface for the icon shape registry. The generated
|
|
30
|
+
* `a-icon.shapes.d.ts` augments this interface with one key per
|
|
31
|
+
* available shape; consumers can do the same with their own generated
|
|
32
|
+
* .d.ts files (TypeScript merges them by interface name).
|
|
33
|
+
*/
|
|
34
|
+
export interface IconShapes {
|
|
35
|
+
}
|
|
36
|
+
export type IconShape = keyof IconShapes;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { Progress } from "./components/Progress";
|
|
2
|
+
import { Text } from "./components/Text";
|
|
3
|
+
import { Icon } from "./components/Icon";
|
|
4
|
+
import { ICON_SHAPES, ICON_SYNONYMS } from "./elements/a-icon.shapes";
|
|
2
5
|
import { configure } from "./jsx-runtime";
|
|
3
6
|
export {
|
|
7
|
+
ICON_SHAPES,
|
|
8
|
+
ICON_SYNONYMS,
|
|
9
|
+
Icon,
|
|
4
10
|
Progress,
|
|
11
|
+
Text,
|
|
5
12
|
configure
|
|
6
13
|
};
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -4,11 +4,25 @@ type JsxFunction = {
|
|
|
4
4
|
h(type: ComponentType, props: Record<string, unknown> | null, ...children: unknown[]): unknown;
|
|
5
5
|
}['h'];
|
|
6
6
|
declare let _Fragment: ComponentType;
|
|
7
|
+
/**
|
|
8
|
+
* Swap the underlying JSX factory used by all anta components.
|
|
9
|
+
*
|
|
10
|
+
* Not needed for React or Preact-with-compat — those work automatically.
|
|
11
|
+
* Call this before rendering any anta components when using Preact without
|
|
12
|
+
* compat aliasing, or a custom JSX runtime.
|
|
13
|
+
*
|
|
14
|
+
* @example Preact without compat
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { configure } from '@antadesign/anta'
|
|
17
|
+
* import { h, Fragment } from 'preact'
|
|
18
|
+
* configure(h, Fragment)
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
7
21
|
export declare function configure(jsx: JsxFunction, Fragment?: ComponentType): void;
|
|
8
22
|
export declare function jsx(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
9
23
|
export declare function jsxs(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
10
24
|
export { _Fragment as Fragment };
|
|
11
|
-
import type { AProgressAttributes, BaseAttributes } from './general_types';
|
|
25
|
+
import type { AProgressAttributes, ATextAttributes, AIconAttributes, BaseAttributes } from './general_types';
|
|
12
26
|
export declare namespace JSX {
|
|
13
27
|
type IntrinsicElements = React.JSX.IntrinsicElements & {
|
|
14
28
|
'a-progress': AProgressAttributes;
|
|
@@ -16,5 +30,7 @@ export declare namespace JSX {
|
|
|
16
30
|
'a-progress-number': BaseAttributes;
|
|
17
31
|
'a-progress-text': BaseAttributes;
|
|
18
32
|
'a-progress-hint': BaseAttributes;
|
|
33
|
+
'a-text': ATextAttributes;
|
|
34
|
+
'a-icon': AIconAttributes;
|
|
19
35
|
};
|
|
20
36
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antadesign/anta",
|
|
3
|
-
"version": "0.1.1-dev.
|
|
3
|
+
"version": "0.1.1-dev.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"NOTICES.md"
|
|
10
|
+
],
|
|
11
|
+
"packageManager": "pnpm@8.13.1",
|
|
8
12
|
"exports": {
|
|
9
13
|
".": {
|
|
10
14
|
"types": "./dist/index.d.ts",
|
|
@@ -22,6 +26,8 @@
|
|
|
22
26
|
"types": "./dist/elements/*.d.ts",
|
|
23
27
|
"default": "./dist/elements/*.js"
|
|
24
28
|
},
|
|
29
|
+
"./anta_global_tokens.css": "./dist/anta_global_tokens.css",
|
|
30
|
+
"./generate-icons.mjs": "./dist/generate-icons.mjs",
|
|
25
31
|
"./*": {
|
|
26
32
|
"types": "./dist/*.d.ts",
|
|
27
33
|
"default": "./dist/*"
|
|
@@ -29,10 +35,11 @@
|
|
|
29
35
|
},
|
|
30
36
|
"scripts": {
|
|
31
37
|
"build": "pnpm run build:js && pnpm run build:css && pnpm run build:types",
|
|
32
|
-
"build:css": "cp src/elements/a-progress.css dist/elements/ && cp src/components/Progress.module.css dist/components/",
|
|
33
|
-
"build:js": "esbuild src/components/Progress.tsx src/index.ts src/jsx-runtime.ts src/general_types.ts src/anta_helpers.ts src/elements/index.ts src/elements/a-progress.ts --outdir=dist --outbase=src --jsx=automatic --jsx-import-source=@antadesign/anta --format=esm --target=ES2022 --loader:.module.css=local-css --loader:.css=global-css",
|
|
38
|
+
"build:css": "cp src/elements/a-progress.css src/elements/a-text.css src/elements/a-icon.css src/elements/a-icon.shapes.css dist/elements/ && cp src/components/Progress.module.css src/components/Text.module.css dist/components/ && cp src/anta_global_tokens.css dist/ && cp scripts/generate-icons.mjs dist/",
|
|
39
|
+
"build:js": "esbuild src/components/Progress.tsx src/components/Text.tsx src/components/Icon.tsx src/index.ts src/jsx-runtime.ts src/general_types.ts src/anta_helpers.ts src/elements/index.ts src/elements/a-progress.ts src/elements/a-text.ts src/elements/a-icon.ts src/elements/a-icon.shapes.ts --outdir=dist --outbase=src --jsx=automatic --jsx-import-source=@antadesign/anta --format=esm --target=ES2022 --loader:.module.css=local-css --loader:.css=global-css",
|
|
34
40
|
"build:types": "tsc -p src/tsconfig.json",
|
|
35
41
|
"typecheck": "tsc --noEmit -p src/tsconfig.json",
|
|
42
|
+
"icons": "node scripts/generate-icons.mjs --input src/elements/icons --output src/elements --name a-icon.shapes --internal",
|
|
36
43
|
"clean": "rm -rf dist"
|
|
37
44
|
},
|
|
38
45
|
"devDependencies": {
|