@zseven-w/pen-types 0.0.1
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 +31 -0
- package/package.json +21 -0
- package/src/canvas.ts +31 -0
- package/src/design-md.ts +24 -0
- package/src/index.ts +73 -0
- package/src/pen.ts +221 -0
- package/src/styles.ts +108 -0
- package/src/theme-preset.ts +17 -0
- package/src/uikit.ts +42 -0
- package/src/variables.ts +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @zseven-w/pen-types
|
|
2
|
+
|
|
3
|
+
Type definitions for the [OpenPencil](https://github.com/nicepkg/openpencil) document model.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @zseven-w/pen-types
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What's Included
|
|
12
|
+
|
|
13
|
+
This package provides all TypeScript types and interfaces for the OpenPencil design file format (`.op`):
|
|
14
|
+
|
|
15
|
+
- **Document model** — `PenDocument`, `PenPage`, `PenNode` and all node types (`FrameNode`, `RectangleNode`, `EllipseNode`, `TextNode`, `ImageNode`, `PathNode`, etc.)
|
|
16
|
+
- **Styles** — `PenFill` (solid, gradient, image), `PenStroke`, `PenEffect` (blur, shadow), `BlendMode`, `StyledTextSegment`
|
|
17
|
+
- **Variables & Themes** — `VariableDefinition`, `VariableValue`, `ThemedValue`
|
|
18
|
+
- **Canvas state** — `ToolType`, `ViewportState`, `SelectionState`, `CanvasInteraction`
|
|
19
|
+
- **UIKit** — `UIKit`, `KitComponent`, `ComponentCategory`
|
|
20
|
+
- **Theme presets** — `ThemePreset`, `ThemePresetFile`
|
|
21
|
+
- **Design spec** — `DesignMdSpec`, `DesignMdColor`, `DesignMdTypography`
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import type { PenDocument, PenNode, FrameNode } from '@zseven-w/pen-types'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## License
|
|
30
|
+
|
|
31
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zseven-w/pen-types",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Type definitions for OpenPencil document model",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./src/index.ts",
|
|
9
|
+
"import": "./src/index.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"typecheck": "tsc --noEmit"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"typescript": "^5.7.2"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/canvas.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type ToolType =
|
|
2
|
+
| 'select'
|
|
3
|
+
| 'frame'
|
|
4
|
+
| 'rectangle'
|
|
5
|
+
| 'ellipse'
|
|
6
|
+
| 'line'
|
|
7
|
+
| 'polygon'
|
|
8
|
+
| 'path'
|
|
9
|
+
| 'text'
|
|
10
|
+
| 'hand'
|
|
11
|
+
|
|
12
|
+
export interface ViewportState {
|
|
13
|
+
zoom: number
|
|
14
|
+
panX: number
|
|
15
|
+
panY: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SelectionState {
|
|
19
|
+
selectedIds: string[]
|
|
20
|
+
activeId: string | null
|
|
21
|
+
hoveredId: string | null
|
|
22
|
+
enteredFrameId: string | null
|
|
23
|
+
enteredFrameStack: string[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface CanvasInteraction {
|
|
27
|
+
isDrawing: boolean
|
|
28
|
+
isPanning: boolean
|
|
29
|
+
isDragging: boolean
|
|
30
|
+
drawStartPoint: { x: number; y: number } | null
|
|
31
|
+
}
|
package/src/design-md.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface DesignMdSpec {
|
|
2
|
+
/** Original markdown source (for round-trip fidelity) */
|
|
3
|
+
raw: string
|
|
4
|
+
projectName?: string
|
|
5
|
+
visualTheme?: string
|
|
6
|
+
colorPalette?: DesignMdColor[]
|
|
7
|
+
typography?: DesignMdTypography
|
|
8
|
+
componentStyles?: string
|
|
9
|
+
layoutPrinciples?: string
|
|
10
|
+
generationNotes?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DesignMdColor {
|
|
14
|
+
name: string
|
|
15
|
+
hex: string
|
|
16
|
+
role: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DesignMdTypography {
|
|
20
|
+
fontFamily?: string
|
|
21
|
+
headings?: string
|
|
22
|
+
body?: string
|
|
23
|
+
scale?: string
|
|
24
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Styles
|
|
2
|
+
export type {
|
|
3
|
+
BlendMode,
|
|
4
|
+
SolidFill,
|
|
5
|
+
GradientStop,
|
|
6
|
+
LinearGradientFill,
|
|
7
|
+
RadialGradientFill,
|
|
8
|
+
ImageFill,
|
|
9
|
+
PenFill,
|
|
10
|
+
PenStroke,
|
|
11
|
+
BlurEffect,
|
|
12
|
+
ShadowEffect,
|
|
13
|
+
PenEffect,
|
|
14
|
+
StyledTextSegment,
|
|
15
|
+
} from './styles.js'
|
|
16
|
+
|
|
17
|
+
// Variables
|
|
18
|
+
export type {
|
|
19
|
+
VariableDefinition,
|
|
20
|
+
VariableValue,
|
|
21
|
+
ThemedValue,
|
|
22
|
+
} from './variables.js'
|
|
23
|
+
|
|
24
|
+
// Canvas
|
|
25
|
+
export type {
|
|
26
|
+
ToolType,
|
|
27
|
+
ViewportState,
|
|
28
|
+
SelectionState,
|
|
29
|
+
CanvasInteraction,
|
|
30
|
+
} from './canvas.js'
|
|
31
|
+
|
|
32
|
+
// Document model
|
|
33
|
+
export type {
|
|
34
|
+
PenPage,
|
|
35
|
+
PenDocument,
|
|
36
|
+
PenNodeType,
|
|
37
|
+
SizingBehavior,
|
|
38
|
+
PenNodeBase,
|
|
39
|
+
ContainerProps,
|
|
40
|
+
FrameNode,
|
|
41
|
+
GroupNode,
|
|
42
|
+
RectangleNode,
|
|
43
|
+
EllipseNode,
|
|
44
|
+
LineNode,
|
|
45
|
+
PolygonNode,
|
|
46
|
+
PathNode,
|
|
47
|
+
TextNode,
|
|
48
|
+
ImageFitMode,
|
|
49
|
+
ImageNode,
|
|
50
|
+
IconFontNode,
|
|
51
|
+
RefNode,
|
|
52
|
+
PenNode,
|
|
53
|
+
} from './pen.js'
|
|
54
|
+
|
|
55
|
+
// UIKit
|
|
56
|
+
export type {
|
|
57
|
+
ComponentCategory,
|
|
58
|
+
KitComponent,
|
|
59
|
+
UIKit,
|
|
60
|
+
} from './uikit.js'
|
|
61
|
+
|
|
62
|
+
// Theme presets
|
|
63
|
+
export type {
|
|
64
|
+
ThemePreset,
|
|
65
|
+
ThemePresetFile,
|
|
66
|
+
} from './theme-preset.js'
|
|
67
|
+
|
|
68
|
+
// Design.md
|
|
69
|
+
export type {
|
|
70
|
+
DesignMdSpec,
|
|
71
|
+
DesignMdColor,
|
|
72
|
+
DesignMdTypography,
|
|
73
|
+
} from './design-md.js'
|
package/src/pen.ts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PenFill,
|
|
3
|
+
PenStroke,
|
|
4
|
+
PenEffect,
|
|
5
|
+
StyledTextSegment,
|
|
6
|
+
} from './styles.js'
|
|
7
|
+
import type { VariableDefinition } from './variables.js'
|
|
8
|
+
|
|
9
|
+
// --- Page ---
|
|
10
|
+
|
|
11
|
+
export interface PenPage {
|
|
12
|
+
id: string
|
|
13
|
+
name: string
|
|
14
|
+
children: PenNode[]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// --- Document Root ---
|
|
18
|
+
|
|
19
|
+
export interface PenDocument {
|
|
20
|
+
version: string
|
|
21
|
+
name?: string
|
|
22
|
+
themes?: Record<string, string[]>
|
|
23
|
+
variables?: Record<string, VariableDefinition>
|
|
24
|
+
pages?: PenPage[]
|
|
25
|
+
children: PenNode[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// --- Node Types ---
|
|
29
|
+
|
|
30
|
+
export type PenNodeType =
|
|
31
|
+
| 'frame'
|
|
32
|
+
| 'group'
|
|
33
|
+
| 'rectangle'
|
|
34
|
+
| 'ellipse'
|
|
35
|
+
| 'line'
|
|
36
|
+
| 'polygon'
|
|
37
|
+
| 'path'
|
|
38
|
+
| 'text'
|
|
39
|
+
| 'image'
|
|
40
|
+
| 'icon_font'
|
|
41
|
+
| 'ref'
|
|
42
|
+
|
|
43
|
+
export type SizingBehavior = number | 'fit_content' | 'fill_container' | string
|
|
44
|
+
|
|
45
|
+
// --- Base ---
|
|
46
|
+
|
|
47
|
+
export interface PenNodeBase {
|
|
48
|
+
id: string
|
|
49
|
+
type: PenNodeType
|
|
50
|
+
name?: string
|
|
51
|
+
role?: string // semantic role for AI generation ("button", "card", "heading", etc.)
|
|
52
|
+
x?: number
|
|
53
|
+
y?: number
|
|
54
|
+
rotation?: number
|
|
55
|
+
opacity?: number | string // number or $variable
|
|
56
|
+
enabled?: boolean | string
|
|
57
|
+
visible?: boolean // default true
|
|
58
|
+
locked?: boolean // default false
|
|
59
|
+
flipX?: boolean
|
|
60
|
+
flipY?: boolean
|
|
61
|
+
theme?: Record<string, string>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// --- Container (shared layout props) ---
|
|
65
|
+
|
|
66
|
+
export interface ContainerProps {
|
|
67
|
+
width?: SizingBehavior
|
|
68
|
+
height?: SizingBehavior
|
|
69
|
+
layout?: 'none' | 'vertical' | 'horizontal'
|
|
70
|
+
gap?: number | string
|
|
71
|
+
padding?:
|
|
72
|
+
| number
|
|
73
|
+
| [number, number]
|
|
74
|
+
| [number, number, number, number]
|
|
75
|
+
| string
|
|
76
|
+
justifyContent?:
|
|
77
|
+
| 'start'
|
|
78
|
+
| 'center'
|
|
79
|
+
| 'end'
|
|
80
|
+
| 'space_between'
|
|
81
|
+
| 'space_around'
|
|
82
|
+
alignItems?: 'start' | 'center' | 'end'
|
|
83
|
+
clipContent?: boolean
|
|
84
|
+
children?: PenNode[]
|
|
85
|
+
cornerRadius?: number | [number, number, number, number]
|
|
86
|
+
fill?: PenFill[]
|
|
87
|
+
stroke?: PenStroke
|
|
88
|
+
effects?: PenEffect[]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// --- Concrete Nodes ---
|
|
92
|
+
|
|
93
|
+
export interface FrameNode extends PenNodeBase, ContainerProps {
|
|
94
|
+
type: 'frame'
|
|
95
|
+
reusable?: boolean
|
|
96
|
+
slot?: string[]
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface GroupNode extends PenNodeBase, ContainerProps {
|
|
100
|
+
type: 'group'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface RectangleNode extends PenNodeBase, ContainerProps {
|
|
104
|
+
type: 'rectangle'
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface EllipseNode extends PenNodeBase {
|
|
108
|
+
type: 'ellipse'
|
|
109
|
+
width?: SizingBehavior
|
|
110
|
+
height?: SizingBehavior
|
|
111
|
+
cornerRadius?: number
|
|
112
|
+
innerRadius?: number
|
|
113
|
+
startAngle?: number
|
|
114
|
+
sweepAngle?: number
|
|
115
|
+
fill?: PenFill[]
|
|
116
|
+
stroke?: PenStroke
|
|
117
|
+
effects?: PenEffect[]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface LineNode extends PenNodeBase {
|
|
121
|
+
type: 'line'
|
|
122
|
+
x2?: number
|
|
123
|
+
y2?: number
|
|
124
|
+
stroke?: PenStroke
|
|
125
|
+
effects?: PenEffect[]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface PolygonNode extends PenNodeBase {
|
|
129
|
+
type: 'polygon'
|
|
130
|
+
polygonCount: number
|
|
131
|
+
width?: SizingBehavior
|
|
132
|
+
height?: SizingBehavior
|
|
133
|
+
cornerRadius?: number
|
|
134
|
+
fill?: PenFill[]
|
|
135
|
+
stroke?: PenStroke
|
|
136
|
+
effects?: PenEffect[]
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface PathNode extends PenNodeBase {
|
|
140
|
+
type: 'path'
|
|
141
|
+
iconId?: string // Iconify icon ID, e.g. "lucide:home"
|
|
142
|
+
d: string
|
|
143
|
+
width?: SizingBehavior
|
|
144
|
+
height?: SizingBehavior
|
|
145
|
+
fill?: PenFill[]
|
|
146
|
+
stroke?: PenStroke
|
|
147
|
+
effects?: PenEffect[]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface TextNode extends PenNodeBase {
|
|
151
|
+
type: 'text'
|
|
152
|
+
width?: SizingBehavior
|
|
153
|
+
height?: SizingBehavior
|
|
154
|
+
content: string | StyledTextSegment[]
|
|
155
|
+
fontFamily?: string
|
|
156
|
+
fontSize?: number
|
|
157
|
+
fontWeight?: number | string
|
|
158
|
+
fontStyle?: 'normal' | 'italic'
|
|
159
|
+
letterSpacing?: number
|
|
160
|
+
lineHeight?: number
|
|
161
|
+
textAlign?: 'left' | 'center' | 'right' | 'justify'
|
|
162
|
+
textAlignVertical?: 'top' | 'middle' | 'bottom'
|
|
163
|
+
textGrowth?: 'auto' | 'fixed-width' | 'fixed-width-height'
|
|
164
|
+
underline?: boolean
|
|
165
|
+
strikethrough?: boolean
|
|
166
|
+
fill?: PenFill[]
|
|
167
|
+
effects?: PenEffect[]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export type ImageFitMode = 'fill' | 'fit' | 'crop' | 'tile'
|
|
171
|
+
|
|
172
|
+
export interface ImageNode extends PenNodeBase {
|
|
173
|
+
type: 'image'
|
|
174
|
+
src: string
|
|
175
|
+
objectFit?: ImageFitMode
|
|
176
|
+
width?: SizingBehavior
|
|
177
|
+
height?: SizingBehavior
|
|
178
|
+
cornerRadius?: number | [number, number, number, number]
|
|
179
|
+
effects?: PenEffect[]
|
|
180
|
+
exposure?: number // -100 to 100
|
|
181
|
+
contrast?: number // -100 to 100
|
|
182
|
+
saturation?: number // -100 to 100
|
|
183
|
+
temperature?: number // -100 to 100
|
|
184
|
+
tint?: number // -100 to 100
|
|
185
|
+
highlights?: number // -100 to 100
|
|
186
|
+
shadows?: number // -100 to 100
|
|
187
|
+
imagePrompt?: string // Descriptive prompt for AI image generation (long)
|
|
188
|
+
imageSearchQuery?: string // Short keywords for image search (e.g. "burger fries")
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface IconFontNode extends PenNodeBase {
|
|
192
|
+
type: 'icon_font'
|
|
193
|
+
iconFontName: string
|
|
194
|
+
iconFontFamily?: string
|
|
195
|
+
width?: SizingBehavior
|
|
196
|
+
height?: SizingBehavior
|
|
197
|
+
fill?: PenFill[]
|
|
198
|
+
stroke?: PenStroke
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface RefNode extends PenNodeBase {
|
|
202
|
+
type: 'ref'
|
|
203
|
+
ref: string
|
|
204
|
+
descendants?: Record<string, Partial<PenNode>>
|
|
205
|
+
children?: PenNode[]
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// --- Union ---
|
|
209
|
+
|
|
210
|
+
export type PenNode =
|
|
211
|
+
| FrameNode
|
|
212
|
+
| GroupNode
|
|
213
|
+
| RectangleNode
|
|
214
|
+
| EllipseNode
|
|
215
|
+
| LineNode
|
|
216
|
+
| PolygonNode
|
|
217
|
+
| PathNode
|
|
218
|
+
| TextNode
|
|
219
|
+
| ImageNode
|
|
220
|
+
| IconFontNode
|
|
221
|
+
| RefNode
|
package/src/styles.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export type BlendMode =
|
|
2
|
+
| 'normal'
|
|
3
|
+
| 'darken'
|
|
4
|
+
| 'multiply'
|
|
5
|
+
| 'screen'
|
|
6
|
+
| 'overlay'
|
|
7
|
+
| 'lighten'
|
|
8
|
+
| 'difference'
|
|
9
|
+
| 'hue'
|
|
10
|
+
| 'saturation'
|
|
11
|
+
| 'color'
|
|
12
|
+
| 'luminosity'
|
|
13
|
+
|
|
14
|
+
// --- Fill Types ---
|
|
15
|
+
|
|
16
|
+
export interface SolidFill {
|
|
17
|
+
type: 'solid'
|
|
18
|
+
color: string // #RRGGBB or #RRGGBBAA
|
|
19
|
+
opacity?: number
|
|
20
|
+
blendMode?: BlendMode
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface GradientStop {
|
|
24
|
+
offset: number // 0 to 1
|
|
25
|
+
color: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface LinearGradientFill {
|
|
29
|
+
type: 'linear_gradient'
|
|
30
|
+
angle?: number
|
|
31
|
+
stops: GradientStop[]
|
|
32
|
+
opacity?: number
|
|
33
|
+
blendMode?: BlendMode
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface RadialGradientFill {
|
|
37
|
+
type: 'radial_gradient'
|
|
38
|
+
cx?: number
|
|
39
|
+
cy?: number
|
|
40
|
+
radius?: number
|
|
41
|
+
stops: GradientStop[]
|
|
42
|
+
opacity?: number
|
|
43
|
+
blendMode?: BlendMode
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ImageFill {
|
|
47
|
+
type: 'image'
|
|
48
|
+
url: string
|
|
49
|
+
mode?: 'fill' | 'fit' | 'crop' | 'tile' | 'stretch'
|
|
50
|
+
opacity?: number
|
|
51
|
+
exposure?: number // -100 to 100
|
|
52
|
+
contrast?: number // -100 to 100
|
|
53
|
+
saturation?: number // -100 to 100
|
|
54
|
+
temperature?: number // -100 to 100
|
|
55
|
+
tint?: number // -100 to 100
|
|
56
|
+
highlights?: number // -100 to 100
|
|
57
|
+
shadows?: number // -100 to 100
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type PenFill =
|
|
61
|
+
| SolidFill
|
|
62
|
+
| LinearGradientFill
|
|
63
|
+
| RadialGradientFill
|
|
64
|
+
| ImageFill
|
|
65
|
+
|
|
66
|
+
// --- Stroke ---
|
|
67
|
+
|
|
68
|
+
export interface PenStroke {
|
|
69
|
+
thickness: number | [number, number, number, number]
|
|
70
|
+
align?: 'inside' | 'center' | 'outside'
|
|
71
|
+
join?: 'miter' | 'bevel' | 'round'
|
|
72
|
+
cap?: 'none' | 'round' | 'square'
|
|
73
|
+
dashPattern?: number[]
|
|
74
|
+
fill?: PenFill[]
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// --- Effects ---
|
|
78
|
+
|
|
79
|
+
export interface BlurEffect {
|
|
80
|
+
type: 'blur' | 'background_blur'
|
|
81
|
+
radius: number
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ShadowEffect {
|
|
85
|
+
type: 'shadow'
|
|
86
|
+
inner?: boolean
|
|
87
|
+
offsetX: number
|
|
88
|
+
offsetY: number
|
|
89
|
+
blur: number
|
|
90
|
+
spread: number
|
|
91
|
+
color: string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type PenEffect = BlurEffect | ShadowEffect
|
|
95
|
+
|
|
96
|
+
// --- Text ---
|
|
97
|
+
|
|
98
|
+
export interface StyledTextSegment {
|
|
99
|
+
text: string
|
|
100
|
+
fontFamily?: string
|
|
101
|
+
fontSize?: number
|
|
102
|
+
fontWeight?: number
|
|
103
|
+
fontStyle?: 'normal' | 'italic'
|
|
104
|
+
fill?: string
|
|
105
|
+
underline?: boolean
|
|
106
|
+
strikethrough?: boolean
|
|
107
|
+
href?: string
|
|
108
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { VariableDefinition } from './variables.js'
|
|
2
|
+
|
|
3
|
+
export interface ThemePreset {
|
|
4
|
+
id: string
|
|
5
|
+
name: string
|
|
6
|
+
themes: Record<string, string[]>
|
|
7
|
+
variables: Record<string, VariableDefinition>
|
|
8
|
+
createdAt: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ThemePresetFile {
|
|
12
|
+
type: 'openpencil-theme-preset'
|
|
13
|
+
version: '1.0.0'
|
|
14
|
+
name: string
|
|
15
|
+
themes: Record<string, string[]>
|
|
16
|
+
variables: Record<string, VariableDefinition>
|
|
17
|
+
}
|
package/src/uikit.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { PenDocument } from './pen.js'
|
|
2
|
+
|
|
3
|
+
export type ComponentCategory =
|
|
4
|
+
| 'buttons'
|
|
5
|
+
| 'inputs'
|
|
6
|
+
| 'cards'
|
|
7
|
+
| 'navigation'
|
|
8
|
+
| 'layout'
|
|
9
|
+
| 'feedback'
|
|
10
|
+
| 'data-display'
|
|
11
|
+
| 'other'
|
|
12
|
+
|
|
13
|
+
export interface KitComponent {
|
|
14
|
+
/** Node ID of the reusable FrameNode in the kit document */
|
|
15
|
+
id: string
|
|
16
|
+
/** Display name */
|
|
17
|
+
name: string
|
|
18
|
+
/** Category for organization in the browser */
|
|
19
|
+
category: ComponentCategory
|
|
20
|
+
/** Tags for search */
|
|
21
|
+
tags: string[]
|
|
22
|
+
/** Component dimensions for preview sizing */
|
|
23
|
+
width: number
|
|
24
|
+
height: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface UIKit {
|
|
28
|
+
/** Unique identifier */
|
|
29
|
+
id: string
|
|
30
|
+
/** Display name */
|
|
31
|
+
name: string
|
|
32
|
+
/** Optional description */
|
|
33
|
+
description?: string
|
|
34
|
+
/** Version string */
|
|
35
|
+
version: string
|
|
36
|
+
/** Whether this is a built-in kit that ships with the app */
|
|
37
|
+
builtIn: boolean
|
|
38
|
+
/** Backing PenDocument containing the reusable nodes */
|
|
39
|
+
document: PenDocument
|
|
40
|
+
/** Extracted component metadata for browsing */
|
|
41
|
+
components: KitComponent[]
|
|
42
|
+
}
|
package/src/variables.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface VariableDefinition {
|
|
2
|
+
type: 'color' | 'number' | 'boolean' | 'string'
|
|
3
|
+
value: VariableValue
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type VariableValue = string | number | boolean | ThemedValue[]
|
|
7
|
+
|
|
8
|
+
export interface ThemedValue {
|
|
9
|
+
value: string | number | boolean
|
|
10
|
+
theme?: Record<string, string>
|
|
11
|
+
}
|