@girumtech/gs-design-system-react 0.1.4
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/README.md +148 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @girumtech/gs-design-system-react
|
|
2
|
+
|
|
3
|
+
React web entry point for GsDesignSystem, a TypeScript design system built with Tamagui. It exports the shared components, four themes, path-based icons, and curated web-compatible layout primitives.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- React 19 or newer
|
|
8
|
+
- React DOM 19 or newer
|
|
9
|
+
- Tamagui 2.7
|
|
10
|
+
- React Native Web 0.21 or newer
|
|
11
|
+
- React Native SVG 15 or newer
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @girumtech/gs-design-system-react tamagui react-native-web react-native-svg
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Vite setup
|
|
20
|
+
|
|
21
|
+
Tamagui uses React Native-compatible modules on the web. Alias `react-native` to `react-native-web` and expose the build environment in Vite:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// vite.config.ts
|
|
25
|
+
import { defineConfig } from 'vite'
|
|
26
|
+
import react from '@vitejs/plugin-react'
|
|
27
|
+
|
|
28
|
+
export default defineConfig(({ mode }) => ({
|
|
29
|
+
plugins: [react()],
|
|
30
|
+
define: {
|
|
31
|
+
'process.env': JSON.stringify({
|
|
32
|
+
NODE_ENV: mode === 'production' ? 'production' : 'development',
|
|
33
|
+
TAMAGUI_HEADLESS: '0',
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
resolve: {
|
|
37
|
+
alias: {
|
|
38
|
+
'react-native': 'react-native-web',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
}))
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Application setup
|
|
45
|
+
|
|
46
|
+
Add `GsProvider` once near the application root. It supplies the Tamagui configuration, tokens, and default theme.
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
// src/main.tsx
|
|
50
|
+
import { StrictMode } from 'react'
|
|
51
|
+
import { createRoot } from 'react-dom/client'
|
|
52
|
+
import { GsProvider } from '@girumtech/gs-design-system-react'
|
|
53
|
+
import { App } from './App'
|
|
54
|
+
|
|
55
|
+
createRoot(document.getElementById('root')!).render(
|
|
56
|
+
<StrictMode>
|
|
57
|
+
<GsProvider defaultTheme="blue">
|
|
58
|
+
<App />
|
|
59
|
+
</GsProvider>
|
|
60
|
+
</StrictMode>,
|
|
61
|
+
)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Available themes are `red`, `red_dark`, `blue`, and `blue_dark`.
|
|
65
|
+
|
|
66
|
+
## Components
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { Button, Field, Text, XStack, YStack } from '@girumtech/gs-design-system-react'
|
|
70
|
+
|
|
71
|
+
export function SignIn() {
|
|
72
|
+
return (
|
|
73
|
+
<YStack maxWidth={420} padding="$5" gap="$4" backgroundColor="$background">
|
|
74
|
+
<Text variant="title">Welcome back</Text>
|
|
75
|
+
<Text tone="muted">Sign in to continue.</Text>
|
|
76
|
+
|
|
77
|
+
<Field
|
|
78
|
+
id="email"
|
|
79
|
+
label="Email"
|
|
80
|
+
placeholder="you@example.com"
|
|
81
|
+
helperText="Use your work email."
|
|
82
|
+
/>
|
|
83
|
+
|
|
84
|
+
<XStack gap="$3">
|
|
85
|
+
<Button onPress={() => console.log('Continue')}>Continue</Button>
|
|
86
|
+
<Button intent="secondary">Cancel</Button>
|
|
87
|
+
</XStack>
|
|
88
|
+
</YStack>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Buttons and inputs use the active theme accent for their border by default. Override it with the standard Tamagui `borderColor` prop:
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
<Button borderColor="#7C3AED">Custom border</Button>
|
|
97
|
+
<Field id="code" label="Code" borderColor="#7C3AED" />
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Switching and forcing themes
|
|
101
|
+
|
|
102
|
+
Use `Theme` to force a theme for a subtree. The theme name is fully typed.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import { Theme, View, Text, type GsThemeName } from '@girumtech/gs-design-system-react'
|
|
106
|
+
|
|
107
|
+
const theme: GsThemeName = 'red_dark'
|
|
108
|
+
|
|
109
|
+
export function AlertPreview() {
|
|
110
|
+
return (
|
|
111
|
+
<Theme name={theme}>
|
|
112
|
+
<View padding="$4" backgroundColor="$background">
|
|
113
|
+
<Text tone="accent">This subtree uses red dark.</Text>
|
|
114
|
+
</View>
|
|
115
|
+
</Theme>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Icons
|
|
121
|
+
|
|
122
|
+
Use a built-in icon or provide one or more SVG path definitions:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import { Icon, NamedIcon, type IconPath } from '@girumtech/gs-design-system-react'
|
|
126
|
+
|
|
127
|
+
const spark: readonly IconPath[] = [
|
|
128
|
+
{
|
|
129
|
+
d: 'M12 2 14.5 9.5 22 12l-7.5 2.5L12 22l-2.5-7.5L2 12l7.5-2.5L12 2Z',
|
|
130
|
+
fill: 'currentColor',
|
|
131
|
+
},
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
export function Icons() {
|
|
135
|
+
return (
|
|
136
|
+
<>
|
|
137
|
+
<NamedIcon name="heart" size={28} color="#A81D1D" label="Favorite" />
|
|
138
|
+
<Icon paths={spark} size={32} color="#10106B" label="Spark" />
|
|
139
|
+
</>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Decorative icons may omit `label`; meaningful icons should provide one.
|
|
145
|
+
|
|
146
|
+
## Exports
|
|
147
|
+
|
|
148
|
+
The package exports `GsProvider`, `Theme`, `Button`, `Input`, `Field`, `Text`, `Icon`, `NamedIcon`, tokens, themes, and the curated `Anchor`, `Image`, `ScrollView`, `Separator`, `View`, `XStack`, `YStack`, and `ZStack` primitives.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IconPath, IconName } from '@girumtech/gs-design-system-core';
|
|
2
|
+
export * from '@girumtech/gs-design-system-core';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { SVGProps } from 'react';
|
|
5
|
+
export { Anchor, Image, ScrollView, Separator, View, XStack, YStack, ZStack } from 'tamagui';
|
|
6
|
+
|
|
7
|
+
interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'children' | 'color'> {
|
|
8
|
+
paths: readonly IconPath[];
|
|
9
|
+
size?: number;
|
|
10
|
+
color?: string;
|
|
11
|
+
viewBox?: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function Icon({ paths, size, color, viewBox, label, style, ...props }: IconProps): react.JSX.Element;
|
|
15
|
+
declare function NamedIcon({ name, ...props }: Omit<IconProps, 'paths'> & {
|
|
16
|
+
name: IconName;
|
|
17
|
+
}): react.JSX.Element;
|
|
18
|
+
|
|
19
|
+
export { Icon, type IconProps, NamedIcon };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
export * from "@girumtech/gs-design-system-core";
|
|
3
|
+
|
|
4
|
+
// src/icon.tsx
|
|
5
|
+
import { icons, normalizeIconPaths } from "@girumtech/gs-design-system-core";
|
|
6
|
+
import { useTheme } from "tamagui";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
function Icon({ paths, size = 24, color = "currentColor", viewBox = "0 0 24 24", label, style, ...props }) {
|
|
9
|
+
const theme = useTheme();
|
|
10
|
+
const themeColor = color.startsWith("$") ? theme[color.slice(1)]?.get() ?? color : color;
|
|
11
|
+
const normalized = normalizeIconPaths(paths, themeColor);
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
"svg",
|
|
14
|
+
{
|
|
15
|
+
width: size,
|
|
16
|
+
height: size,
|
|
17
|
+
viewBox,
|
|
18
|
+
color: themeColor,
|
|
19
|
+
role: label ? "img" : void 0,
|
|
20
|
+
"aria-label": label,
|
|
21
|
+
"aria-hidden": label ? void 0 : true,
|
|
22
|
+
focusable: "false",
|
|
23
|
+
style: { display: "block", flexShrink: 0, ...style },
|
|
24
|
+
...props,
|
|
25
|
+
children: normalized.map((path, index) => /* @__PURE__ */ jsx("path", { ...path }, `${path.d}-${index}`))
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
function NamedIcon({ name, ...props }) {
|
|
30
|
+
return /* @__PURE__ */ jsx(Icon, { paths: icons[name], ...props });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/index.ts
|
|
34
|
+
import { Anchor, Image, ScrollView, Separator, View, XStack, YStack, ZStack } from "tamagui";
|
|
35
|
+
export {
|
|
36
|
+
Anchor,
|
|
37
|
+
Icon,
|
|
38
|
+
Image,
|
|
39
|
+
NamedIcon,
|
|
40
|
+
ScrollView,
|
|
41
|
+
Separator,
|
|
42
|
+
View,
|
|
43
|
+
XStack,
|
|
44
|
+
YStack,
|
|
45
|
+
ZStack
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/icon.tsx"],"sourcesContent":["export * from '@girumtech/gs-design-system-core'\nexport { Icon, NamedIcon, type IconProps } from './icon'\nexport { Anchor, Image, ScrollView, Separator, View, XStack, YStack, ZStack } from 'tamagui'\n","import type { SVGProps } from 'react'\nimport { icons, normalizeIconPaths, type IconName, type IconPath } from '@girumtech/gs-design-system-core'\nimport { useTheme } from 'tamagui'\n\nexport interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'children' | 'color'> {\n paths: readonly IconPath[]\n size?: number\n color?: string\n viewBox?: string\n label?: string\n}\n\nexport function Icon({ paths, size = 24, color = 'currentColor', viewBox = '0 0 24 24', label, style, ...props }: IconProps) {\n const theme = useTheme()\n const themeColor = color.startsWith('$')\n ? (theme[color.slice(1) as keyof typeof theme]?.get() as string | undefined) ?? color\n : color\n const normalized = normalizeIconPaths(paths, themeColor)\n return (\n <svg\n width={size}\n height={size}\n viewBox={viewBox}\n color={themeColor}\n role={label ? 'img' : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n focusable=\"false\"\n style={{ display: 'block', flexShrink: 0, ...style }}\n {...props}\n >\n {normalized.map((path, index) => <path key={`${path.d}-${index}`} {...path} />)}\n </svg>\n )\n}\n\nexport function NamedIcon({ name, ...props }: Omit<IconProps, 'paths'> & { name: IconName }) {\n return <Icon paths={icons[name]} {...props} />\n}\n"],"mappings":";AAAA,cAAc;;;ACCd,SAAS,OAAO,0BAAwD;AACxE,SAAS,gBAAgB;AA6Bc;AAnBhC,SAAS,KAAK,EAAE,OAAO,OAAO,IAAI,QAAQ,gBAAgB,UAAU,aAAa,OAAO,OAAO,GAAG,MAAM,GAAc;AAC3H,QAAM,QAAQ,SAAS;AACvB,QAAM,aAAa,MAAM,WAAW,GAAG,IAClC,MAAM,MAAM,MAAM,CAAC,CAAuB,GAAG,IAAI,KAA4B,QAC9E;AACJ,QAAM,aAAa,mBAAmB,OAAO,UAAU;AACvD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR;AAAA,MACA,OAAO;AAAA,MACP,MAAM,QAAQ,QAAQ;AAAA,MACtB,cAAY;AAAA,MACZ,eAAa,QAAQ,SAAY;AAAA,MACjC,WAAU;AAAA,MACV,OAAO,EAAE,SAAS,SAAS,YAAY,GAAG,GAAG,MAAM;AAAA,MAClD,GAAG;AAAA,MAEH,qBAAW,IAAI,CAAC,MAAM,UAAU,oBAAC,UAAiC,GAAG,QAA1B,GAAG,KAAK,CAAC,IAAI,KAAK,EAAc,CAAE;AAAA;AAAA,EAChF;AAEJ;AAEO,SAAS,UAAU,EAAE,MAAM,GAAG,MAAM,GAAkD;AAC3F,SAAO,oBAAC,QAAK,OAAO,MAAM,IAAI,GAAI,GAAG,OAAO;AAC9C;;;ADpCA,SAAS,QAAQ,OAAO,YAAY,WAAW,MAAM,QAAQ,QAAQ,cAAc;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@girumtech/gs-design-system-react",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "React web entry point for GsDesignSystem",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"module": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"typecheck": "tsc -p tsconfig.json"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@girumtech/gs-design-system-core": "0.1.4"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=19",
|
|
30
|
+
"react-dom": ">=19",
|
|
31
|
+
"react-native-svg": ">=15",
|
|
32
|
+
"react-native-web": ">=0.21",
|
|
33
|
+
"tamagui": ">=2.7.0 <3"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|