snice 3.4.0 → 3.5.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 (177) hide show
  1. package/bin/templates/base/package.json +2 -2
  2. package/bin/templates/social/package.json +2 -2
  3. package/bin/templates/social/src/styles/global.css +56 -47
  4. package/dist/components/avatar/snice-avatar.d.ts +2 -2
  5. package/dist/components/avatar/snice-avatar.js +20 -21
  6. package/dist/components/avatar/snice-avatar.js.map +1 -1
  7. package/dist/components/calendar/snice-calendar.d.ts +8 -2
  8. package/dist/components/calendar/snice-calendar.js +160 -82
  9. package/dist/components/calendar/snice-calendar.js.map +1 -1
  10. package/dist/components/chart/snice-chart.js +50 -18
  11. package/dist/components/chart/snice-chart.js.map +1 -1
  12. package/dist/components/checkbox/snice-checkbox.d.ts +4 -1
  13. package/dist/components/checkbox/snice-checkbox.js +46 -17
  14. package/dist/components/checkbox/snice-checkbox.js.map +1 -1
  15. package/dist/components/code-block/highlighter.d.ts +5 -0
  16. package/dist/components/code-block/highlighter.js +137 -0
  17. package/dist/components/code-block/highlighter.js.map +1 -0
  18. package/dist/components/code-block/highlighters/highlight.d.ts +64 -0
  19. package/dist/components/code-block/highlighters/highlight.js +108 -0
  20. package/dist/components/code-block/highlighters/highlight.js.map +1 -0
  21. package/dist/components/code-block/highlighters/prism.d.ts +41 -0
  22. package/dist/components/code-block/highlighters/prism.js +73 -0
  23. package/dist/components/code-block/highlighters/prism.js.map +1 -0
  24. package/dist/components/code-block/snice-code-block.d.ts +19 -1
  25. package/dist/components/code-block/snice-code-block.js +128 -29
  26. package/dist/components/code-block/snice-code-block.js.map +1 -1
  27. package/dist/components/code-block/snice-code-block.types.d.ts +15 -1
  28. package/dist/components/color-picker/snice-color-picker.d.ts +1 -0
  29. package/dist/components/color-picker/snice-color-picker.js +17 -6
  30. package/dist/components/color-picker/snice-color-picker.js.map +1 -1
  31. package/dist/components/date-picker/snice-date-picker.d.ts +1 -0
  32. package/dist/components/date-picker/snice-date-picker.js +16 -5
  33. package/dist/components/date-picker/snice-date-picker.js.map +1 -1
  34. package/dist/components/doc/snice-doc.d.ts +27 -73
  35. package/dist/components/doc/snice-doc.js +385 -534
  36. package/dist/components/doc/snice-doc.js.map +1 -1
  37. package/dist/components/draw/snice-draw.d.ts +4 -0
  38. package/dist/components/draw/snice-draw.js +134 -14
  39. package/dist/components/draw/snice-draw.js.map +1 -1
  40. package/dist/components/draw/snice-draw.types.d.ts +5 -0
  41. package/dist/components/file-upload/snice-file-upload.js +1 -1
  42. package/dist/components/input/snice-input.d.ts +2 -0
  43. package/dist/components/input/snice-input.js +34 -9
  44. package/dist/components/input/snice-input.js.map +1 -1
  45. package/dist/components/kanban/snice-kanban.d.ts +13 -1
  46. package/dist/components/kanban/snice-kanban.js +191 -36
  47. package/dist/components/kanban/snice-kanban.js.map +1 -1
  48. package/dist/components/kanban/snice-kanban.types.d.ts +11 -1
  49. package/dist/components/kpi/snice-kpi.js +5 -1
  50. package/dist/components/kpi/snice-kpi.js.map +1 -1
  51. package/dist/components/layout/snice-layout-sidebar.js +1 -1
  52. package/dist/components/layout/snice-layout-sidebar.js.map +1 -1
  53. package/dist/components/layout/snice-layout.js +1 -1
  54. package/dist/components/layout/snice-layout.js.map +1 -1
  55. package/dist/components/location/snice-location.js +1 -1
  56. package/dist/components/location/snice-location.js.map +1 -1
  57. package/dist/components/radio/snice-radio.d.ts +1 -0
  58. package/dist/components/radio/snice-radio.js +17 -6
  59. package/dist/components/radio/snice-radio.js.map +1 -1
  60. package/dist/components/select/snice-select.d.ts +2 -0
  61. package/dist/components/select/snice-select.js +48 -19
  62. package/dist/components/select/snice-select.js.map +1 -1
  63. package/dist/components/slider/snice-slider.d.ts +2 -0
  64. package/dist/components/slider/snice-slider.js +34 -14
  65. package/dist/components/slider/snice-slider.js.map +1 -1
  66. package/dist/components/snice-cell-HZ2iIBIC.js +4 -0
  67. package/dist/components/snice-cell-HZ2iIBIC.js.map +1 -0
  68. package/dist/components/split-pane/snice-split-pane.js +1 -1
  69. package/dist/components/split-pane/snice-split-pane.js.map +1 -1
  70. package/dist/components/switch/snice-switch.d.ts +1 -0
  71. package/dist/components/switch/snice-switch.js +16 -6
  72. package/dist/components/switch/snice-switch.js.map +1 -1
  73. package/dist/components/table/snice-cell-actions.js +1 -1
  74. package/dist/components/table/snice-cell-actions.js.map +1 -1
  75. package/dist/components/table/snice-cell-boolean.js +1 -1
  76. package/dist/components/table/snice-cell-color.js +1 -1
  77. package/dist/components/table/snice-cell-color.js.map +1 -1
  78. package/dist/components/table/snice-cell-currency.js +1 -1
  79. package/dist/components/table/snice-cell-date.js +1 -1
  80. package/dist/components/table/snice-cell-duration.js +1 -1
  81. package/dist/components/table/snice-cell-email.js +1 -1
  82. package/dist/components/table/snice-cell-email.js.map +1 -1
  83. package/dist/components/table/snice-cell-filesize.js +1 -1
  84. package/dist/components/table/snice-cell-image.js +1 -1
  85. package/dist/components/table/snice-cell-image.js.map +1 -1
  86. package/dist/components/table/snice-cell-json.js +1 -1
  87. package/dist/components/table/snice-cell-json.js.map +1 -1
  88. package/dist/components/table/snice-cell-link.js +1 -1
  89. package/dist/components/table/snice-cell-link.js.map +1 -1
  90. package/dist/components/table/snice-cell-location.js +1 -1
  91. package/dist/components/table/snice-cell-location.js.map +1 -1
  92. package/dist/components/table/snice-cell-number.js +1 -1
  93. package/dist/components/table/snice-cell-percentage.js +1 -1
  94. package/dist/components/table/snice-cell-percentage.js.map +1 -1
  95. package/dist/components/table/snice-cell-phone.js +1 -1
  96. package/dist/components/table/snice-cell-phone.js.map +1 -1
  97. package/dist/components/table/snice-cell-progress.js +3 -3
  98. package/dist/components/table/snice-cell-progress.js.map +1 -1
  99. package/dist/components/table/snice-cell-rating.js +2 -2
  100. package/dist/components/table/snice-cell-rating.js.map +1 -1
  101. package/dist/components/table/snice-cell-sparkline.js +2 -2
  102. package/dist/components/table/snice-cell-sparkline.js.map +1 -1
  103. package/dist/components/table/snice-cell-status.js +1 -1
  104. package/dist/components/table/snice-cell-status.js.map +1 -1
  105. package/dist/components/table/snice-cell-tag.js +1 -1
  106. package/dist/components/table/snice-cell-tag.js.map +1 -1
  107. package/dist/components/table/snice-cell-text.js +1 -1
  108. package/dist/components/table/snice-cell.js +15 -10
  109. package/dist/components/table/snice-cell.js.map +1 -1
  110. package/dist/components/table/snice-header.js +1 -1
  111. package/dist/components/table/snice-header.js.map +1 -1
  112. package/dist/components/table/snice-row.js +2 -2
  113. package/dist/components/table/snice-row.js.map +1 -1
  114. package/dist/components/table/snice-table.d.ts +1 -0
  115. package/dist/components/table/snice-table.js +24 -4
  116. package/dist/components/table/snice-table.js.map +1 -1
  117. package/dist/components/terminal/snice-terminal.d.ts +40 -0
  118. package/dist/components/terminal/snice-terminal.js +371 -0
  119. package/dist/components/terminal/snice-terminal.js.map +1 -0
  120. package/dist/components/terminal/snice-terminal.types.d.ts +20 -24
  121. package/dist/components/textarea/snice-textarea.d.ts +2 -0
  122. package/dist/components/textarea/snice-textarea.js +25 -6
  123. package/dist/components/textarea/snice-textarea.js.map +1 -1
  124. package/dist/components/theme/theme.css +16 -0
  125. package/dist/components/tree/snice-tree-item.d.ts +18 -4
  126. package/dist/components/tree/snice-tree-item.js +271 -88
  127. package/dist/components/tree/snice-tree-item.js.map +1 -1
  128. package/dist/components/tree/snice-tree-item.types.d.ts +3 -0
  129. package/dist/components/tree/snice-tree.d.ts +18 -2
  130. package/dist/components/tree/snice-tree.js +422 -56
  131. package/dist/components/tree/snice-tree.js.map +1 -1
  132. package/dist/components/tree/snice-tree.types.d.ts +1 -0
  133. package/dist/components/virtual-scroller/snice-virtual-scroller.js +4 -2
  134. package/dist/components/virtual-scroller/snice-virtual-scroller.js.map +1 -1
  135. package/dist/index.cjs +42 -23
  136. package/dist/index.cjs.map +1 -1
  137. package/dist/index.esm.js +42 -23
  138. package/dist/index.esm.js.map +1 -1
  139. package/dist/index.iife.js +42 -23
  140. package/dist/index.iife.js.map +1 -1
  141. package/dist/render-tracker.d.ts +1 -0
  142. package/dist/symbols.cjs +13 -14
  143. package/dist/symbols.cjs.map +1 -1
  144. package/dist/symbols.esm.js +13 -14
  145. package/dist/symbols.esm.js.map +1 -1
  146. package/dist/template.d.ts +1 -0
  147. package/dist/transitions.cjs +1 -1
  148. package/dist/transitions.esm.js +1 -1
  149. package/docs/ai/api.md +37 -4
  150. package/docs/ai/components/doc.md +41 -106
  151. package/docs/ai/components/kanban.md +31 -9
  152. package/docs/ai/components/kpi.md +15 -0
  153. package/docs/components/doc.md +96 -212
  154. package/docs/components/kanban.md +119 -4
  155. package/docs/components/kpi.md +27 -0
  156. package/package.json +4 -1
  157. package/dist/components/actions/snice-actions.d.ts +0 -28
  158. package/dist/components/actions/snice-actions.js +0 -220
  159. package/dist/components/actions/snice-actions.js.map +0 -1
  160. package/dist/components/actions/snice-actions.types.d.ts +0 -27
  161. package/dist/components/doc/snice-doc.types.d.ts +0 -118
  162. package/dist/components/gantt/snice-gantt.d.ts +0 -29
  163. package/dist/components/gantt/snice-gantt.js +0 -268
  164. package/dist/components/gantt/snice-gantt.js.map +0 -1
  165. package/dist/components/gantt/snice-gantt.types.d.ts +0 -23
  166. package/dist/components/snice-cell-C0slgOpe.js +0 -4
  167. package/dist/components/snice-cell-C0slgOpe.js.map +0 -1
  168. package/dist/components/stat/snice-stat.d.ts +0 -14
  169. package/dist/components/stat/snice-stat.js +0 -140
  170. package/dist/components/stat/snice-stat.js.map +0 -1
  171. package/dist/components/stat/snice-stat.types.d.ts +0 -12
  172. package/docs/ai/components/actions.md +0 -81
  173. package/docs/ai/components/gantt.md +0 -95
  174. package/docs/ai/components/stat.md +0 -29
  175. package/docs/components/actions.md +0 -317
  176. package/docs/components/gantt.md +0 -347
  177. package/docs/components/stat.md +0 -45
@@ -1,15 +1,15 @@
1
1
  # snice-doc
2
2
 
3
- A Notion-like document editor component with block-based editing, multiple content types, and rich export capabilities.
3
+ A simple WYSIWYG document editor component with formatting toolbar and content insertion capabilities.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Block-based editing** - Create and organize content using blocks
8
- - **Multiple block types** - Headings, paragraphs, lists, code, quotes, dividers, and to-dos
9
- - **Block menu** - Type `/` to open a searchable block type menu
7
+ - **WYSIWYG editing** - Direct HTML content editing
8
+ - **Formatting toolbar** - Bold, italic, underline, strikethrough, headings, lists
9
+ - **Content insertion** - Links, images, tables, dividers
10
+ - **Sidebar controls** - Quick access to insert images, tables, and dividers
11
+ - **Paste image support** - Paste images directly from clipboard
10
12
  - **Keyboard shortcuts** - Ctrl/Cmd+B for bold, Ctrl/Cmd+I for italic, Ctrl/Cmd+U for underline
11
- - **Drag and drop** - Reorder blocks by dragging the handle
12
- - **Export formats** - JSON, Markdown, and HTML export
13
13
  - **Readonly mode** - Display documents without editing capabilities
14
14
  - **Customizable styling** - CSS custom properties for theming
15
15
 
@@ -23,173 +23,78 @@ A Notion-like document editor component with block-based editing, multiple conte
23
23
 
24
24
  const editor = document.getElementById('editor');
25
25
 
26
- // Listen for changes
27
- editor.addEventListener('doc-change', (e) => {
28
- console.log('Document changed:', e.detail.blocks);
29
- });
26
+ // Set initial content
27
+ editor.setHTML('<h1>Welcome</h1><p>Start editing...</p>');
28
+
29
+ // Get content
30
+ const html = editor.getHTML();
31
+ console.log(html);
30
32
  </script>
31
33
  ```
32
34
 
33
- ## Block Types
34
-
35
- The editor supports the following block types:
36
-
37
- - `paragraph` - Regular text paragraph
38
- - `heading-1` - Top-level heading
39
- - `heading-2` - Second-level heading
40
- - `heading-3` - Third-level heading
41
- - `bulleted-list` - Bulleted list item
42
- - `numbered-list` - Numbered list item
43
- - `todo` - To-do list item with checkbox
44
- - `code` - Code block with monospace font
45
- - `quote` - Blockquote for citations
46
- - `divider` - Horizontal divider line
47
-
48
35
  ## Properties
49
36
 
50
- | Property | Attribute | Type | Default | Description |
51
- | ------------- | ------------- | ----------- | ----------------------------- | ---------------------------------- |
52
- | `blocks` | - | `DocBlock[]` | `[{...}]` | Document blocks (property only) |
53
- | `placeholder` | `placeholder` | `string` | `"Type '/' for commands..."` | Placeholder text when empty |
54
- | `readonly` | `readonly` | `boolean` | `false` | Whether the editor is readonly |
37
+ | Property | Attribute | Type | Default | Description |
38
+ | ------------- | ------------- | --------- | -------------------- | -------------------------------- |
39
+ | `placeholder` | `placeholder` | `string` | `"Start typing..."` | Placeholder text when empty |
40
+ | `readonly` | `readonly` | `boolean` | `false` | Whether the editor is readonly |
55
41
 
56
42
  ## Methods
57
43
 
58
- ### `getBlocks(): DocBlock[]`
59
-
60
- Get a copy of all blocks in the document.
61
-
62
- ```javascript
63
- const blocks = editor.getBlocks();
64
- console.log(blocks);
65
- ```
66
-
67
- ### `setBlocks(blocks: DocBlock[]): void`
68
-
69
- Set the document blocks.
70
-
71
- ```javascript
72
- editor.setBlocks([
73
- { id: '1', type: 'heading-1', content: 'Title', formats: [] },
74
- { id: '2', type: 'paragraph', content: 'Content', formats: [] },
75
- ]);
76
- ```
77
-
78
- ### `toJSON(): string`
79
-
80
- Export the document as formatted JSON.
81
-
82
- ```javascript
83
- const json = editor.toJSON();
84
- console.log(json);
85
- ```
86
-
87
- ### `fromJSON(json: string): void`
88
-
89
- Import a document from JSON.
90
-
91
- ```javascript
92
- const json = '[ {"id": "1", "type": "paragraph", "content": "Hello", "formats": []} ]';
93
- editor.fromJSON(json);
94
- ```
95
-
96
- ### `toMarkdown(): string`
97
-
98
- Export the document as Markdown.
99
-
100
- ```javascript
101
- const markdown = editor.toMarkdown();
102
- console.log(markdown);
103
- // # Title
104
- //
105
- // Content
106
- ```
107
-
108
- ### `toHTML(): string`
44
+ ### `getHTML(): string`
109
45
 
110
- Export the document as HTML.
46
+ Get the current HTML content of the editor.
111
47
 
112
48
  ```javascript
113
- const html = editor.toHTML();
49
+ const html = editor.getHTML();
114
50
  console.log(html);
115
- // <h1>Title</h1>
116
- // <p>Content</p>
117
51
  ```
118
52
 
119
- ### `focus(): void`
53
+ ### `setHTML(html: string): void`
120
54
 
121
- Focus the editor (focuses the first block).
55
+ Set the HTML content of the editor.
122
56
 
123
57
  ```javascript
124
- editor.focus();
58
+ editor.setHTML(`
59
+ <h1>Welcome!</h1>
60
+ <p>This is a <b>simple</b> document editor.</p>
61
+ `);
125
62
  ```
126
63
 
127
64
  ### `clear(): void`
128
65
 
129
- Clear all content and reset to a single empty paragraph.
66
+ Clear all content and reset to an empty paragraph.
130
67
 
131
68
  ```javascript
132
69
  editor.clear();
133
70
  ```
134
71
 
135
- ## Events
72
+ ## Toolbar Features
136
73
 
137
- ### `doc-change`
74
+ The toolbar includes:
138
75
 
139
- Emitted when the document content changes.
76
+ - **B** - Bold text (Ctrl/Cmd+B)
77
+ - **I** - Italic text (Ctrl/Cmd+I)
78
+ - **U** - Underline text (Ctrl/Cmd+U)
79
+ - **S** - Strikethrough text
80
+ - **H1, H2, H3, P** - Heading formats and paragraph
81
+ - **• / 1.** - Bulleted and numbered lists
82
+ - **🔗** - Insert link
83
+ - **🖼** - Insert image
140
84
 
141
- ```javascript
142
- editor.addEventListener('doc-change', (e) => {
143
- console.log('Changed blocks:', e.detail.blocks);
144
- });
145
- ```
146
-
147
- **Detail:**
148
- - `blocks: DocBlock[]` - The updated blocks array
149
-
150
- ### `doc-focus`
151
-
152
- Emitted when a block receives focus.
153
-
154
- ```javascript
155
- editor.addEventListener('doc-focus', (e) => {
156
- console.log('Focused block:', e.detail.blockId);
157
- });
158
- ```
85
+ ## Sidebar Features
159
86
 
160
- **Detail:**
161
- - `blockId: string` - The ID of the focused block
87
+ The collapsible sidebar provides quick access to:
162
88
 
163
- ### `doc-blur`
164
-
165
- Emitted when a block loses focus.
166
-
167
- ```javascript
168
- editor.addEventListener('doc-blur', (e) => {
169
- console.log('Blurred block:', e.detail.blockId);
170
- });
171
- ```
172
-
173
- **Detail:**
174
- - `blockId: string` - The ID of the blurred block
89
+ - **Image** - Insert image via URL dialog
90
+ - **Table** - Insert table with custom rows/columns
91
+ - **Divider** - Insert horizontal rule
175
92
 
176
93
  ## Keyboard Shortcuts
177
94
 
178
- ### Editor Shortcuts
179
-
180
- - **Enter** - Create new paragraph block
181
- - **Backspace** (on empty block) - Delete block
182
- - **Ctrl/Cmd+B** - Toggle bold (planned)
183
- - **Ctrl/Cmd+I** - Toggle italic (planned)
184
- - **Ctrl/Cmd+U** - Toggle underline (planned)
185
-
186
- ### Block Menu Shortcuts
187
-
188
- - **/** - Open block menu
189
- - **ArrowDown** - Navigate down in menu
190
- - **ArrowUp** - Navigate up in menu
191
- - **Enter** - Select highlighted block type
192
- - **Escape** - Close block menu
95
+ - **Ctrl/Cmd+B** - Toggle bold
96
+ - **Ctrl/Cmd+I** - Toggle italic
97
+ - **Ctrl/Cmd+U** - Toggle underline
193
98
 
194
99
  ## Styling
195
100
 
@@ -205,32 +110,19 @@ snice-doc {
205
110
  --snice-doc-primary-color: #0969da;
206
111
  --snice-doc-link-color: #0969da;
207
112
 
208
- /* Code blocks */
209
- --snice-doc-code-background: #f6f8fa;
210
- --snice-doc-code-border: #e1e4e8;
113
+ /* Code */
211
114
  --snice-doc-inline-code-background: rgba(175, 184, 193, 0.2);
212
115
 
213
- /* Quotes */
214
- --snice-doc-quote-border: #e1e4e8;
215
-
216
- /* Divider */
217
- --snice-doc-divider-color: #e1e4e8;
116
+ /* Toolbar */
117
+ --snice-doc-toolbar-background: #f6f8fa;
118
+ --snice-doc-toolbar-border: #e1e4e8;
218
119
 
219
- /* Block menu */
220
- --snice-doc-menu-background: #fff;
221
- --snice-doc-menu-border: #e1e4e8;
222
- --snice-doc-menu-hover: #f6f8fa;
223
-
224
- /* Format toolbar */
225
- --snice-doc-toolbar-background: #1f2328;
226
- --snice-doc-toolbar-text: #fff;
227
- --snice-doc-toolbar-hover: rgba(255, 255, 255, 0.1);
228
- --snice-doc-toolbar-active: rgba(88, 166, 255, 0.3);
120
+ /* Sidebar */
121
+ --snice-doc-sidebar-background: #f6f8fa;
122
+ --snice-doc-sidebar-border: #e1e4e8;
229
123
 
230
124
  /* Spacing */
231
- --snice-doc-padding: 40px 20px;
232
- --snice-doc-min-height: 400px;
233
- --snice-doc-max-width: 900px;
125
+ --snice-doc-padding: 20px;
234
126
  }
235
127
  ```
236
128
 
@@ -245,58 +137,61 @@ snice-doc {
245
137
  import 'snice';
246
138
 
247
139
  const viewer = document.querySelector('snice-doc');
248
- viewer.setBlocks([
249
- { id: '1', type: 'heading-1', content: 'Read Only Document', formats: [] },
250
- { id: '2', type: 'paragraph', content: 'This document cannot be edited.', formats: [] },
251
- ]);
140
+ viewer.setHTML(`
141
+ <h1>Read Only Document</h1>
142
+ <p>This document cannot be edited.</p>
143
+ `);
252
144
  </script>
253
145
  ```
254
146
 
255
- ### Document with To-do List
147
+ ### Rich Content Document
256
148
 
257
149
  ```html
258
- <snice-doc id="todos"></snice-doc>
150
+ <snice-doc id="editor"></snice-doc>
259
151
 
260
152
  <script type="module">
261
153
  import 'snice';
262
154
 
263
- const todos = document.getElementById('todos');
264
- todos.setBlocks([
265
- { id: '1', type: 'heading-2', content: 'My Tasks', formats: [] },
266
- { id: '2', type: 'todo', content: 'Write documentation', formats: [], checked: true },
267
- { id: '3', type: 'todo', content: 'Review PRs', formats: [], checked: false },
268
- { id: '4', type: 'todo', content: 'Deploy to production', formats: [], checked: false },
269
- ]);
155
+ const editor = document.getElementById('editor');
156
+ editor.setHTML(`
157
+ <h1>Welcome to the Document Editor!</h1>
158
+ <p>This is a simple document editor with:</p>
159
+ <ul>
160
+ <li><b>Bold</b>, <i>italic</i>, <u>underline</u> formatting</li>
161
+ <li>Headings (H1, H2, H3)</li>
162
+ <li>Bullet and numbered lists</li>
163
+ <li>Images and links</li>
164
+ <li>Tables</li>
165
+ </ul>
166
+ <p>Try typing with <b>bold</b> and hitting Enter - the formatting continues naturally!</p>
167
+ `);
270
168
  </script>
271
169
  ```
272
170
 
273
- ### Export to Multiple Formats
171
+ ### Save and Load Content
274
172
 
275
173
  ```html
276
174
  <snice-doc id="editor"></snice-doc>
277
- <button id="export-json">Export JSON</button>
278
- <button id="export-md">Export Markdown</button>
279
- <button id="export-html">Export HTML</button>
175
+ <button id="save">Save</button>
176
+ <button id="load">Load</button>
280
177
 
281
178
  <script type="module">
282
179
  import 'snice';
283
180
 
284
181
  const editor = document.getElementById('editor');
285
182
 
286
- document.getElementById('export-json').addEventListener('click', () => {
287
- const json = editor.toJSON();
288
- console.log(json);
289
- // Download or copy to clipboard
290
- });
291
-
292
- document.getElementById('export-md').addEventListener('click', () => {
293
- const markdown = editor.toMarkdown();
294
- console.log(markdown);
183
+ document.getElementById('save').addEventListener('click', () => {
184
+ const html = editor.getHTML();
185
+ localStorage.setItem('document', html);
186
+ console.log('Saved!');
295
187
  });
296
188
 
297
- document.getElementById('export-html').addEventListener('click', () => {
298
- const html = editor.toHTML();
299
- console.log(html);
189
+ document.getElementById('load').addEventListener('click', () => {
190
+ const html = localStorage.getItem('document');
191
+ if (html) {
192
+ editor.setHTML(html);
193
+ console.log('Loaded!');
194
+ }
300
195
  });
301
196
  </script>
302
197
  ```
@@ -310,48 +205,37 @@ snice-doc {
310
205
  --snice-doc-background: #0d1117;
311
206
  --snice-doc-muted-color: #7d8590;
312
207
  --snice-doc-placeholder-color: #484f58;
313
- --snice-doc-code-background: #161b22;
314
- --snice-doc-code-border: #30363d;
315
- --snice-doc-quote-border: #30363d;
316
- --snice-doc-divider-color: #21262d;
208
+ --snice-doc-toolbar-background: #161b22;
209
+ --snice-doc-toolbar-border: #30363d;
210
+ --snice-doc-sidebar-background: #161b22;
211
+ --snice-doc-sidebar-border: #30363d;
317
212
  }
318
213
  </style>
319
214
 
320
215
  <snice-doc class="dark"></snice-doc>
321
216
  ```
322
217
 
323
- ## Block Data Structure
324
-
325
- Each block in the document has the following structure:
326
-
327
- ```typescript
328
- interface DocBlock {
329
- id: string; // Unique identifier
330
- type: BlockType; // Block type (see Block Types section)
331
- content: string; // Text content
332
- formats: TextRange[]; // Inline formatting (future)
333
- checked?: boolean; // For todo blocks
334
- indent?: number; // For nested lists (future)
335
- }
336
- ```
337
-
338
218
  ## Accessibility
339
219
 
340
220
  - Supports keyboard navigation
341
- - Uses semantic HTML in exports
342
- - ARIA attributes for better screen reader support (future improvement)
221
+ - Uses contentEditable for native text editing
222
+ - Semantic HTML output
343
223
 
344
224
  ## Browser Support
345
225
 
346
226
  Works in all modern browsers that support:
347
227
  - Custom Elements v1
348
228
  - Shadow DOM
229
+ - contentEditable
349
230
  - ES2020+
350
231
 
351
232
  ## TypeScript
352
233
 
353
- Full TypeScript support with exported types:
234
+ Full TypeScript support:
354
235
 
355
236
  ```typescript
356
- import type { DocBlock, BlockType, SniceDocElement } from 'snice/doc';
237
+ import type { SniceDoc } from 'snice/doc';
238
+
239
+ const editor = document.querySelector<SniceDoc>('snice-doc');
240
+ const html = editor?.getHTML();
357
241
  ```
@@ -44,6 +44,18 @@ interface KanbanColumn {
44
44
  }
45
45
  ```
46
46
 
47
+ ## KanbanLabel Interface
48
+
49
+ ```typescript
50
+ interface KanbanLabel {
51
+ text: string;
52
+ color?: string; // Text color
53
+ background?: string; // Background color
54
+ icon?: string; // Emoji or text icon
55
+ iconPosition?: 'left' | 'right'; // Icon placement
56
+ }
57
+ ```
58
+
47
59
  ## KanbanCard Interface
48
60
 
49
61
  ```typescript
@@ -52,7 +64,7 @@ interface KanbanCard {
52
64
  title: string;
53
65
  description?: string;
54
66
  assignee?: string;
55
- labels?: string[];
67
+ labels?: (string | KanbanLabel)[]; // String or full label object
56
68
  color?: string;
57
69
  data?: any;
58
70
  }
@@ -96,11 +108,36 @@ Remove card from board.
96
108
  kanban.removeCard(10);
97
109
  ```
98
110
 
99
- ### `moveCard(cardId: string | number, targetColumnId: string | number): void`
100
- Move card to different column.
111
+ ### `moveCard(cardId: string | number, targetColumnId: string | number, targetIndex?: number): void`
112
+ Move card to different column (and optionally specific position).
101
113
 
102
114
  ```javascript
115
+ // Move to different column
103
116
  kanban.moveCard(1, 'done');
117
+
118
+ // Move to specific position in column
119
+ kanban.moveCard(1, 'done', 0); // Move to top
120
+ ```
121
+
122
+ ### `filterByLabels(labels: string[]): void`
123
+ Filter cards by labels (shows cards with ANY of the specified labels).
124
+
125
+ ```javascript
126
+ kanban.filterByLabels(['bug', 'high-priority']);
127
+ ```
128
+
129
+ ### `search(query: string): void`
130
+ Search cards by title or description.
131
+
132
+ ```javascript
133
+ kanban.search('landing page');
134
+ ```
135
+
136
+ ### `clearFilters(): void`
137
+ Clear all active filters (labels and search).
138
+
139
+ ```javascript
140
+ kanban.clearFilters();
104
141
  ```
105
142
 
106
143
  ### `getColumn(id: string | number): KanbanColumn | undefined`
@@ -147,6 +184,79 @@ kanban.addEventListener('@snice/kanban-card-click', (e) => {
147
184
 
148
185
  ## Examples
149
186
 
187
+ ### Custom Labels with Icons
188
+
189
+ Labels can be simple strings or rich objects with custom colors and icons:
190
+
191
+ ```javascript
192
+ kanban.columns = [
193
+ {
194
+ id: 'todo',
195
+ title: 'To Do',
196
+ cards: [
197
+ {
198
+ id: 1,
199
+ title: 'Redesign dashboard',
200
+ labels: [
201
+ // Simple string label (uses default theme styling)
202
+ 'feature',
203
+ // Rich label with custom colors and icon
204
+ {
205
+ text: 'High Priority',
206
+ color: '#dc2626',
207
+ background: '#fee2e2',
208
+ icon: '🔥',
209
+ iconPosition: 'left'
210
+ }
211
+ ]
212
+ },
213
+ {
214
+ id: 2,
215
+ title: 'Analytics dashboard',
216
+ labels: [
217
+ {
218
+ text: 'Analytics',
219
+ color: '#0891b2',
220
+ background: '#cffafe',
221
+ icon: '📊',
222
+ iconPosition: 'left'
223
+ },
224
+ {
225
+ text: 'Shipped',
226
+ color: '#16a34a',
227
+ background: '#dcfce7',
228
+ icon: '🚀',
229
+ iconPosition: 'right' // Icon on the right
230
+ }
231
+ ]
232
+ }
233
+ ]
234
+ }
235
+ ];
236
+ ```
237
+
238
+ ### Filtering and Search
239
+
240
+ Filter cards by labels or search by text:
241
+
242
+ ```javascript
243
+ // Filter by single label
244
+ kanban.filterByLabels(['bug']);
245
+
246
+ // Filter by multiple labels (shows cards with ANY of these labels)
247
+ kanban.filterByLabels(['bug', 'high-priority']);
248
+
249
+ // Search by title or description
250
+ kanban.search('landing page');
251
+
252
+ // Combine filters and search (both apply)
253
+ kanban.filterByLabels(['feature']);
254
+ kanban.search('dashboard');
255
+
256
+ // Clear all filters
257
+ kanban.clearFilters();
258
+ ```
259
+
150
260
  ### Basic Board
151
261
 
152
262
  ```javascript
@@ -190,7 +300,10 @@ kanban.columns = [
190
300
  title: 'Design Landing Page',
191
301
  description: 'Create mockups and wireframes',
192
302
  assignee: 'Alice',
193
- labels: ['design', 'high-priority'],
303
+ labels: [
304
+ 'design',
305
+ { text: 'high-priority', color: '#dc2626', background: '#fee2e2', icon: '⚡' }
306
+ ],
194
307
  color: '#f44336'
195
308
  }
196
309
  ]
@@ -407,4 +520,6 @@ kanban.addEventListener('@snice/kanban-card-move', async (e) => {
407
520
 
408
521
  - Modern browsers with Custom Elements v1 support
409
522
  - HTML5 Drag and Drop API
523
+ - View Transitions API (optional, for smooth animations)
524
+ - Drag and drop between columns and within same column
410
525
  - Touch events for mobile (future enhancement)
@@ -2,9 +2,12 @@
2
2
 
3
3
  A key performance indicator display component for showing metrics with optional trend visualization and sentiment indicators. Perfect for dashboards and analytics interfaces.
4
4
 
5
+ > **Note**: The `snice-stat` component has been merged into `snice-kpi`. All stat functionality is now available through KPI.
6
+
5
7
  ## Features
6
8
 
7
9
  - **Clear Value Display**: Large, prominent metric value
10
+ - **Icon Support**: Optional icon slot for visual branding
8
11
  - **Trend Indicators**: Optional trend value with sentiment icons
9
12
  - **Sparkline Integration**: Built-in sparkline chart support
10
13
  - **Sentiment Colors**: Visual feedback with up/down/neutral states
@@ -31,6 +34,30 @@ A key performance indicator display component for showing metrics with optional
31
34
  | `sentiment` | `KpiSentiment` | `undefined` | Trend sentiment ('up', 'down', 'neutral') |
32
35
  | `size` | `KpiSize` | `'medium'` | Component size ('small', 'medium', 'large') |
33
36
  | `show-sparkline` | `boolean` | `true` | Whether to show sparkline when data is provided |
37
+ | `color-value` | `boolean` | `false` | Apply sentiment color to main value |
38
+
39
+ ## Slots
40
+
41
+ | Slot | Description |
42
+ |------|-------------|
43
+ | `before` | Content displayed before the label/value (e.g., icons) |
44
+ | `after` | Content displayed after sparkline (e.g., additional actions) |
45
+
46
+ ## With Icon (Before Slot)
47
+
48
+ ```html
49
+ <snice-kpi
50
+ label="Total Revenue"
51
+ value="$45,231"
52
+ trend-value="+12%"
53
+ sentiment="up">
54
+ <div slot="before" style="display: flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; background: var(--snice-color-primary-subtle); border-radius: var(--snice-border-radius-md); margin-bottom: var(--snice-spacing-xs);">
55
+ <svg style="width: 1.5rem; height: 1.5rem; color: var(--snice-color-primary); fill: currentColor;" viewBox="0 0 24 24">
56
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/>
57
+ </svg>
58
+ </div>
59
+ </snice-kpi>
60
+ ```
34
61
 
35
62
  ## With Trend Indicator
36
63
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snice",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "type": "module",
5
5
  "description": "Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.",
6
6
  "main": "dist/index.cjs",
@@ -78,10 +78,13 @@
78
78
  },
79
79
  "scripts": {
80
80
  "dev": "vite",
81
+ "sync-versions": "node scripts/sync-template-versions.js",
82
+ "prebuild": "npm run sync-versions",
81
83
  "build": "rm -rf dist && rollup -c && npm run build:types",
82
84
  "build:types": "tsc --project components/tsconfig.json --emitDeclarationOnly",
83
85
  "build:test": "rollup -c rollup.config.test.js",
84
86
  "preview": "vite preview",
87
+ "pretest": "npm run sync-versions",
85
88
  "test": "npm run build:test && vitest run",
86
89
  "test:watch": "vitest",
87
90
  "test:ui": "vitest --ui",
@@ -1,28 +0,0 @@
1
- import type { SniceActionsElement, ActionButton, ActionButtonSize, ActionButtonVariant } from './snice-actions.types';
2
- export declare class SniceActions extends HTMLElement implements SniceActionsElement {
3
- actions: ActionButton[];
4
- size: ActionButtonSize;
5
- variant: ActionButtonVariant;
6
- showLabels: boolean;
7
- maxVisible: number;
8
- moreLabel: string;
9
- moreIcon: string;
10
- private dropdownOpen;
11
- private dispatchActionTrigger;
12
- styles(): import("snice").CSSResult;
13
- triggerAction(id: string): void;
14
- getAction(id: string): ActionButton | undefined;
15
- private handleActionClick;
16
- private toggleDropdown;
17
- private closeDropdown;
18
- private renderActionButton;
19
- template(): import("snice").TemplateResult;
20
- init(): void;
21
- cleanup(): void;
22
- private handleOutsideClick;
23
- }
24
- declare global {
25
- interface HTMLElementTagNameMap {
26
- 'snice-actions': SniceActions;
27
- }
28
- }