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,95 +0,0 @@
1
- # snice-gantt
2
-
3
- Project timeline visualization.
4
-
5
- ## Properties
6
-
7
- ```typescript
8
- tasks: GanttTask[] = [];
9
- viewMode: 'day'|'week'|'month'|'year' = 'day';
10
- showToday: boolean = true;
11
- showProgress: boolean = true;
12
- showDependencies: boolean = false;
13
- minDate: Date | string = '';
14
- maxDate: Date | string = '';
15
- ```
16
-
17
- ## GanttTask
18
-
19
- ```typescript
20
- interface GanttTask {
21
- id: string | number;
22
- name: string;
23
- start: Date | string;
24
- end: Date | string;
25
- progress?: number; // 0-100
26
- dependencies?: (string | number)[];
27
- color?: string;
28
- data?: any;
29
- }
30
- ```
31
-
32
- ## Methods
33
-
34
- ```typescript
35
- getTask(id: string | number): GanttTask | undefined
36
- scrollToToday(): void
37
- scrollToTask(id: string | number): void
38
- ```
39
-
40
- ## Events
41
-
42
- - `@snice/gantt-task-click` - Task clicked (detail: { task, gantt })
43
-
44
- ## Usage
45
-
46
- ```javascript
47
- gantt.tasks = [
48
- {
49
- id: 1,
50
- name: 'Planning',
51
- start: new Date(2024, 0, 1),
52
- end: new Date(2024, 0, 7),
53
- progress: 100,
54
- color: '#4caf50'
55
- },
56
- {
57
- id: 2,
58
- name: 'Development',
59
- start: new Date(2024, 0, 8),
60
- end: new Date(2024, 0, 31),
61
- progress: 45,
62
- color: '#ff9800',
63
- dependencies: [1]
64
- }
65
- ];
66
-
67
- // View modes
68
- gantt.viewMode = 'week'; // day|week|month|year
69
-
70
- // Events
71
- gantt.addEventListener('@snice/gantt-task-click', (e) => {
72
- console.log(e.detail.task);
73
- });
74
- ```
75
-
76
- ```html
77
- <snice-gantt
78
- view-mode="month"
79
- show-dependencies
80
- min-date="2024-01-01"
81
- max-date="2024-12-31">
82
- </snice-gantt>
83
- ```
84
-
85
- ## Features
86
-
87
- - Timeline visualization
88
- - Task bars with progress
89
- - Multiple view modes
90
- - Color-coded tasks
91
- - Task dependencies
92
- - Date range control
93
- - Today indicator
94
- - Click handling
95
- - Programmatic navigation
@@ -1,29 +0,0 @@
1
- # snice-stat
2
-
3
- Statistics display with trends and icons.
4
-
5
- ## Properties
6
-
7
- ```typescript
8
- label: string = '';
9
- value: string | number = '';
10
- change: string | number = '';
11
- trend: 'up'|'down'|'neutral' = 'neutral';
12
- size: 'small'|'medium'|'large' = 'medium';
13
- icon: string = '';
14
- iconImage: string = '';
15
- colorValue: boolean = false;
16
- ```
17
-
18
- ## Usage
19
-
20
- ```html
21
- <snice-stat
22
- label="Revenue"
23
- value="$45,231"
24
- change="+12%"
25
- trend="up"
26
- icon="💰"
27
- color-value>
28
- </snice-stat>
29
- ```
@@ -1,317 +0,0 @@
1
- # Actions Component
2
-
3
- Display a collection of action buttons with overflow menu support.
4
-
5
- ## Basic Usage
6
-
7
- ```javascript
8
- const actions = document.querySelector('snice-actions');
9
- actions.actions = [
10
- { id: 'edit', label: 'Edit', icon: '✏️' },
11
- { id: 'delete', label: 'Delete', icon: '🗑️', danger: true }
12
- ];
13
- ```
14
-
15
- ## Properties
16
-
17
- | Property | Type | Default | Description |
18
- |----------|------|---------|-------------|
19
- | `actions` | `ActionButton[]` | `[]` | Array of action buttons |
20
- | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Button size |
21
- | `variant` | `'text' \| 'outlined' \| 'filled'` | `'text'` | Button variant |
22
- | `showLabels` | `boolean` | `true` | Show button labels |
23
- | `maxVisible` | `number` | `3` | Max visible buttons (0 = all) |
24
- | `moreLabel` | `string` | `'More'` | Label for overflow menu |
25
- | `moreIcon` | `string` | `'⋯'` | Icon for overflow menu |
26
-
27
- ## Action Button Interface
28
-
29
- ```typescript
30
- interface ActionButton {
31
- id: string; // Unique identifier
32
- label?: string; // Button label
33
- icon?: string; // Text/emoji icon
34
- iconImage?: string; // Icon image URL
35
- variant?: ActionButtonVariant; // Override variant
36
- disabled?: boolean; // Disable button
37
- danger?: boolean; // Danger styling
38
- tooltip?: string; // Tooltip text
39
- action?: () => void | Promise<void>; // Click handler
40
- href?: string; // Link URL
41
- target?: string; // Link target
42
- data?: any; // Custom data
43
- }
44
- ```
45
-
46
- ## Methods
47
-
48
- ### `triggerAction(id: string): void`
49
- Programmatically trigger an action by ID.
50
-
51
- ```javascript
52
- actions.triggerAction('edit');
53
- ```
54
-
55
- ### `getAction(id: string): ActionButton | undefined`
56
- Get action configuration by ID.
57
-
58
- ```javascript
59
- const action = actions.getAction('edit');
60
- console.log(action.label); // "Edit"
61
- ```
62
-
63
- ## Events
64
-
65
- ### `@snice/action-trigger`
66
- Dispatched when an action is triggered.
67
-
68
- ```javascript
69
- actions.addEventListener('@snice/action-trigger', (e) => {
70
- console.log('Action:', e.detail.action);
71
- });
72
- ```
73
-
74
- **Detail:** `{ action: ActionButton, actionsElement: SniceActionsElement }`
75
-
76
- ## Examples
77
-
78
- ### Basic Actions
79
-
80
- ```javascript
81
- actions.actions = [
82
- { id: 'view', label: 'View', icon: '👁️' },
83
- { id: 'edit', label: 'Edit', icon: '✏️' },
84
- { id: 'delete', label: 'Delete', icon: '🗑️', danger: true }
85
- ];
86
- ```
87
-
88
- ### Icon Only
89
-
90
- ```html
91
- <snice-actions show-labels="false"></snice-actions>
92
- ```
93
-
94
- ```javascript
95
- actions.actions = [
96
- { id: 'like', icon: '👍', tooltip: 'Like' },
97
- { id: 'share', icon: '📤', tooltip: 'Share' },
98
- { id: 'bookmark', icon: '🔖', tooltip: 'Bookmark' }
99
- ];
100
- ```
101
-
102
- ### Different Variants
103
-
104
- ```html
105
- <!-- Outlined -->
106
- <snice-actions variant="outlined"></snice-actions>
107
-
108
- <!-- Filled -->
109
- <snice-actions variant="filled"></snice-actions>
110
- ```
111
-
112
- ### Different Sizes
113
-
114
- ```html
115
- <snice-actions size="small"></snice-actions>
116
- <snice-actions size="medium"></snice-actions>
117
- <snice-actions size="large"></snice-actions>
118
- ```
119
-
120
- ### With Overflow Menu
121
-
122
- ```html
123
- <snice-actions max-visible="3"></snice-actions>
124
- ```
125
-
126
- ```javascript
127
- // 6 actions, only 3 visible, rest in overflow menu
128
- actions.actions = [
129
- { id: 'view', label: 'View', icon: '👁️' },
130
- { id: 'edit', label: 'Edit', icon: '✏️' },
131
- { id: 'download', label: 'Download', icon: '⬇️' },
132
- { id: 'share', label: 'Share', icon: '📤' },
133
- { id: 'archive', label: 'Archive', icon: '📦' },
134
- { id: 'delete', label: 'Delete', icon: '🗑️', danger: true }
135
- ];
136
- ```
137
-
138
- ### With Action Callbacks
139
-
140
- ```javascript
141
- actions.actions = [
142
- {
143
- id: 'save',
144
- label: 'Save',
145
- icon: '💾',
146
- action: async () => {
147
- await saveData();
148
- console.log('Saved!');
149
- }
150
- },
151
- {
152
- id: 'cancel',
153
- label: 'Cancel',
154
- action: () => {
155
- window.history.back();
156
- }
157
- }
158
- ];
159
- ```
160
-
161
- ### With Links
162
-
163
- ```javascript
164
- actions.actions = [
165
- {
166
- id: 'view',
167
- label: 'View',
168
- icon: '👁️',
169
- href: '/details/123'
170
- },
171
- {
172
- id: 'external',
173
- label: 'Open',
174
- icon: '🔗',
175
- href: 'https://example.com',
176
- target: '_blank'
177
- }
178
- ];
179
- ```
180
-
181
- ### Disabled Actions
182
-
183
- ```javascript
184
- actions.actions = [
185
- { id: 'edit', label: 'Edit', icon: '✏️' },
186
- { id: 'delete', label: 'Delete', icon: '🗑️', disabled: true }
187
- ];
188
- ```
189
-
190
- ### Danger Actions
191
-
192
- ```javascript
193
- actions.actions = [
194
- { id: 'approve', label: 'Approve', icon: '✓' },
195
- { id: 'reject', label: 'Reject', icon: '✗', danger: true }
196
- ];
197
- ```
198
-
199
- ### Custom Icons
200
-
201
- ```javascript
202
- actions.actions = [
203
- {
204
- id: 'settings',
205
- label: 'Settings',
206
- iconImage: '/icons/settings.svg'
207
- }
208
- ];
209
- ```
210
-
211
- ### In Table Cells
212
-
213
- ```html
214
- <table>
215
- <thead>
216
- <tr>
217
- <th>Name</th>
218
- <th>Email</th>
219
- <th>Actions</th>
220
- </tr>
221
- </thead>
222
- <tbody>
223
- <tr>
224
- <td>John Doe</td>
225
- <td>john@example.com</td>
226
- <td>
227
- <snice-actions id="row1" show-labels="false" size="small"></snice-actions>
228
- </td>
229
- </tr>
230
- </tbody>
231
- </table>
232
- ```
233
-
234
- ```javascript
235
- document.getElementById('row1').actions = [
236
- { id: 'view', icon: '👁️', tooltip: 'View' },
237
- { id: 'edit', icon: '✏️', tooltip: 'Edit' },
238
- { id: 'delete', icon: '🗑️', tooltip: 'Delete', danger: true }
239
- ];
240
- ```
241
-
242
- ### Per-Action Variant Override
243
-
244
- ```javascript
245
- actions.actions = [
246
- { id: 'save', label: 'Save', icon: '💾', variant: 'filled' },
247
- { id: 'cancel', label: 'Cancel', variant: 'outlined' },
248
- { id: 'reset', label: 'Reset', variant: 'text' }
249
- ];
250
- ```
251
-
252
- ### With Tooltips
253
-
254
- ```javascript
255
- actions.actions = [
256
- { id: 'edit', icon: '✏️', tooltip: 'Edit item' },
257
- { id: 'delete', icon: '🗑️', tooltip: 'Permanently delete this item', danger: true }
258
- ];
259
- ```
260
-
261
- ### Custom More Button
262
-
263
- ```html
264
- <snice-actions more-label="Options" more-icon="▼"></snice-actions>
265
- ```
266
-
267
- ### Programmatic Triggering
268
-
269
- ```javascript
270
- const actions = document.querySelector('snice-actions');
271
-
272
- actions.actions = [
273
- {
274
- id: 'refresh',
275
- label: 'Refresh',
276
- action: () => location.reload()
277
- }
278
- ];
279
-
280
- // Trigger programmatically
281
- setTimeout(() => {
282
- actions.triggerAction('refresh');
283
- }, 5000);
284
- ```
285
-
286
- ### Event Handling
287
-
288
- ```javascript
289
- const actions = document.querySelector('snice-actions');
290
-
291
- actions.addEventListener('@snice/action-trigger', (e) => {
292
- const { action } = e.detail;
293
-
294
- console.log('Action triggered:', action.id);
295
-
296
- // Custom handling
297
- if (action.id === 'delete') {
298
- if (confirm('Are you sure?')) {
299
- deleteItem();
300
- }
301
- }
302
- });
303
- ```
304
-
305
- ## Accessibility
306
-
307
- - Buttons include `title` attributes for tooltips
308
- - Disabled buttons are properly marked with `disabled` attribute
309
- - Keyboard accessible (Tab, Enter, Space)
310
- - Screen readers announce button labels and states
311
- - Danger actions use semantic color coding
312
-
313
- ## Browser Support
314
-
315
- - Modern browsers with Custom Elements v1 support
316
- - Dropdown menu uses absolute positioning
317
- - Click-outside handling for dropdown