@nuralyui/iconpicker 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.
Files changed (67) hide show
  1. package/bundle.js +2796 -0
  2. package/bundle.js.gz +0 -0
  3. package/controllers/event.controller.d.ts +38 -0
  4. package/controllers/event.controller.d.ts.map +1 -0
  5. package/controllers/event.controller.js +68 -0
  6. package/controllers/event.controller.js.map +1 -0
  7. package/controllers/index.d.ts +9 -0
  8. package/controllers/index.d.ts.map +1 -0
  9. package/controllers/index.js +9 -0
  10. package/controllers/index.js.map +1 -0
  11. package/controllers/search.controller.d.ts +34 -0
  12. package/controllers/search.controller.d.ts.map +1 -0
  13. package/controllers/search.controller.js +55 -0
  14. package/controllers/search.controller.js.map +1 -0
  15. package/controllers/selection.controller.d.ts +27 -0
  16. package/controllers/selection.controller.d.ts.map +1 -0
  17. package/controllers/selection.controller.js +39 -0
  18. package/controllers/selection.controller.js.map +1 -0
  19. package/icon-picker.component.d.ts +119 -0
  20. package/icon-picker.component.d.ts.map +1 -0
  21. package/icon-picker.component.js +337 -0
  22. package/icon-picker.component.js.map +1 -0
  23. package/icon-picker.constant.d.ts +15 -0
  24. package/icon-picker.constant.d.ts.map +1 -0
  25. package/icon-picker.constant.js +31 -0
  26. package/icon-picker.constant.js.map +1 -0
  27. package/icon-picker.style.d.ts +8 -0
  28. package/icon-picker.style.d.ts.map +1 -0
  29. package/icon-picker.style.js +216 -0
  30. package/icon-picker.style.js.map +1 -0
  31. package/icon-picker.types.d.ts +49 -0
  32. package/icon-picker.types.d.ts.map +1 -0
  33. package/icon-picker.types.js +7 -0
  34. package/icon-picker.types.js.map +1 -0
  35. package/index.d.ts +9 -0
  36. package/index.d.ts.map +1 -0
  37. package/index.js +9 -0
  38. package/index.js.map +1 -0
  39. package/interfaces/icon-picker.interface.d.ts +13 -0
  40. package/interfaces/icon-picker.interface.d.ts.map +1 -0
  41. package/interfaces/icon-picker.interface.js +7 -0
  42. package/interfaces/icon-picker.interface.js.map +1 -0
  43. package/interfaces/index.d.ts +7 -0
  44. package/interfaces/index.d.ts.map +1 -0
  45. package/interfaces/index.js +7 -0
  46. package/interfaces/index.js.map +1 -0
  47. package/package.json +37 -0
  48. package/react.d.ts +14 -0
  49. package/react.d.ts.map +1 -0
  50. package/react.js +21 -0
  51. package/react.js.map +1 -0
  52. package/utils/icon-filter.utils.d.ts +29 -0
  53. package/utils/icon-filter.utils.d.ts.map +1 -0
  54. package/utils/icon-filter.utils.js +96 -0
  55. package/utils/icon-filter.utils.js.map +1 -0
  56. package/utils/icon-loader.utils.d.ts +39 -0
  57. package/utils/icon-loader.utils.d.ts.map +1 -0
  58. package/utils/icon-loader.utils.js +115 -0
  59. package/utils/icon-loader.utils.js.map +1 -0
  60. package/utils/index.d.ts +8 -0
  61. package/utils/index.d.ts.map +1 -0
  62. package/utils/index.js +8 -0
  63. package/utils/index.js.map +1 -0
  64. package/utils/lucide-icons.d.ts +10 -0
  65. package/utils/lucide-icons.d.ts.map +1 -0
  66. package/utils/lucide-icons.js +1624 -0
  67. package/utils/lucide-icons.js.map +1 -0
@@ -0,0 +1,337 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ };
12
+ import { LitElement, html, nothing } from 'lit';
13
+ import { customElement, property, state } from 'lit/decorators.js';
14
+ import { styleMap } from 'lit/directives/style-map.js';
15
+ import { classMap } from 'lit/directives/class-map.js';
16
+ import { NuralyUIBaseMixin } from '@nuralyui/common/mixins';
17
+ import '@lit-labs/virtualizer';
18
+ import { grid } from '@lit-labs/virtualizer/layouts/grid.js';
19
+ // Import required components
20
+ import '../dropdown/dropdown.component.js';
21
+ import '../input/input.component.js';
22
+ import '../icon/icon.component.js';
23
+ import '../button/button.component.js';
24
+ // Import styles and types
25
+ import styles from './icon-picker.style.js';
26
+ import { EMPTY_STRING } from './icon-picker.types.js';
27
+ import { DEFAULT_PLACEHOLDER, DEFAULT_SEARCH_PLACEHOLDER, DEFAULT_EMPTY_MESSAGE, SEARCH_DEBOUNCE_DELAY } from './icon-picker.constant.js';
28
+ // Import controllers
29
+ import { IconPickerSelectionController, IconPickerSearchController, IconPickerEventController } from './controllers/index.js';
30
+ // Import utilities
31
+ import { IconLoaderUtils } from './utils/index.js';
32
+ /**
33
+ * Advanced icon picker component with search, virtual scrolling, and accessibility.
34
+ *
35
+ * Uses Lucide icons (1500+ beautiful icons) and provides an intuitive selection interface with
36
+ * search filtering, keyboard navigation, and multiple display options.
37
+ *
38
+ * @example
39
+ * ```html
40
+ * <!-- Basic usage -->
41
+ * <nr-icon-picker></nr-icon-picker>
42
+ *
43
+ * <!-- With value -->
44
+ * <nr-icon-picker value="heart"></nr-icon-picker>
45
+ *
46
+ * <!-- Custom configuration -->
47
+ * <nr-icon-picker
48
+ * value="star"
49
+ * size="large"
50
+ * placement="top"
51
+ * show-search
52
+ * show-clear>
53
+ * </nr-icon-picker>
54
+ * ```
55
+ *
56
+ * @fires nr-icon-picker-change - Icon selection changed
57
+ * @fires nr-icon-picker-open - Dropdown opened
58
+ * @fires nr-icon-picker-close - Dropdown closed
59
+ * @fires nr-icon-picker-search - Search query changed
60
+ * @fires nr-icon-picker-clear - Selection cleared
61
+ *
62
+ * @cssproperty --icon-picker-dropdown-width - Width of dropdown
63
+ * @cssproperty --icon-picker-icon-size - Size of icon items
64
+ * @cssproperty --icon-picker-selected-bg - Selected icon background
65
+ * @cssproperty --icon-picker-selected-border - Selected icon border
66
+ */
67
+ let NrIconPickerElement = class NrIconPickerElement extends NuralyUIBaseMixin(LitElement) {
68
+ constructor() {
69
+ super(...arguments);
70
+ this.requiredComponents = ['nr-dropdown', 'nr-input', 'nr-icon', 'nr-button'];
71
+ // Controllers
72
+ this.selectionController = new IconPickerSelectionController(this);
73
+ this.searchController = new IconPickerSearchController(this, SEARCH_DEBOUNCE_DELAY);
74
+ this.eventController = new IconPickerEventController(this);
75
+ // Public properties
76
+ this.value = EMPTY_STRING;
77
+ this.size = "small" /* IconPickerSize.Small */;
78
+ this.placement = "auto" /* IconPickerPlacement.Auto */;
79
+ this.trigger = "manual" /* IconPickerTrigger.Manual */;
80
+ this.disabled = false;
81
+ this.readonly = false;
82
+ this.placeholder = DEFAULT_PLACEHOLDER;
83
+ this.iconTypes = ["solid" /* IconType.Solid */];
84
+ this.showSearch = true;
85
+ this.showClear = true;
86
+ this.maxVisible = 500;
87
+ // Internal state
88
+ this.dropdownOpen = false;
89
+ this.allIcons = [];
90
+ this.filteredIcons = [];
91
+ this.searchQuery = EMPTY_STRING;
92
+ this.selectedIcon = null;
93
+ this.isLoading = false;
94
+ }
95
+ connectedCallback() {
96
+ super.connectedCallback();
97
+ this.loadIcons();
98
+ }
99
+ /**
100
+ * Load icons from Lucide library
101
+ */
102
+ loadIcons() {
103
+ this.isLoading = true;
104
+ try {
105
+ this.allIcons = IconLoaderUtils.loadIcons(this.iconTypes);
106
+ this.filteredIcons = [...this.allIcons];
107
+ // Set selected icon if value is provided
108
+ if (this.value) {
109
+ this.selectedIcon = this.allIcons.find(icon => icon.name === this.value) || null;
110
+ }
111
+ }
112
+ catch (error) {
113
+ console.error('Failed to load icons:', error);
114
+ }
115
+ finally {
116
+ this.isLoading = false;
117
+ }
118
+ }
119
+ /**
120
+ * Handle icon selection
121
+ */
122
+ handleIconSelect(icon) {
123
+ this.selectionController.selectIcon(icon);
124
+ this.eventController.dispatchChangeEvent(icon.name, icon);
125
+ this.dropdownOpen = false;
126
+ }
127
+ /**
128
+ * Handle search input
129
+ */
130
+ handleSearchInput(e) {
131
+ const query = e.detail.value;
132
+ this.searchController.search(query);
133
+ this.eventController.dispatchSearchEvent(query);
134
+ }
135
+ /**
136
+ * Handle clear button
137
+ */
138
+ handleClear(e) {
139
+ e.stopPropagation();
140
+ this.selectionController.clearSelection();
141
+ this.eventController.dispatchClearEvent();
142
+ this.eventController.dispatchChangeEvent(EMPTY_STRING, null);
143
+ }
144
+ /**
145
+ * Handle dropdown open
146
+ */
147
+ handleDropdownOpen() {
148
+ this.dropdownOpen = true;
149
+ this.eventController.dispatchOpenEvent();
150
+ }
151
+ /**
152
+ * Handle dropdown close
153
+ */
154
+ handleDropdownClose() {
155
+ this.dropdownOpen = false;
156
+ this.searchController.clearSearch();
157
+ this.eventController.dispatchCloseEvent();
158
+ }
159
+ /**
160
+ * Toggle dropdown
161
+ */
162
+ toggleDropdown() {
163
+ this.dropdownOpen = !this.dropdownOpen;
164
+ }
165
+ /**
166
+ * Render trigger button
167
+ */
168
+ renderTrigger() {
169
+ return html `
170
+ <nr-button
171
+ class="trigger-button"
172
+ .disabled=${this.disabled}
173
+ size=${this.size}
174
+ @click=${this.toggleDropdown}
175
+ >
176
+ ${this.selectedIcon
177
+ ? html `
178
+ <nr-icon class="icon-preview" .name=${this.selectedIcon.name}></nr-icon>
179
+ <span class="icon-name">${this.selectedIcon.name}</span>
180
+ `
181
+ : html `<span class="placeholder">${this.placeholder}</span>`}
182
+ ${this.showClear && this.selectedIcon
183
+ ? html `
184
+ <nr-icon
185
+ name="times"
186
+ @click=${this.handleClear}
187
+ style="margin-left: auto; cursor: pointer;"
188
+ ></nr-icon>
189
+ `
190
+ : nothing}
191
+ </nr-button>
192
+ `;
193
+ }
194
+ /**
195
+ * Render icon grid
196
+ */
197
+ renderIconGrid() {
198
+ if (this.isLoading) {
199
+ return html `
200
+ <div class="loading-state">
201
+ <nr-icon name="spinner"></nr-icon>
202
+ <div class="empty-message">Loading icons...</div>
203
+ </div>
204
+ `;
205
+ }
206
+ if (this.filteredIcons.length === 0) {
207
+ return html `
208
+ <div class="empty-state">
209
+ <nr-icon name="search"></nr-icon>
210
+ <div class="empty-message">${DEFAULT_EMPTY_MESSAGE}</div>
211
+ </div>
212
+ `;
213
+ }
214
+ // Limit visible icons for performance
215
+ const visibleIcons = this.filteredIcons.slice(0, this.maxVisible);
216
+ return html `
217
+ <div class="dropdown-content">
218
+ ${this.showSearch
219
+ ? html `
220
+ <div class="search-container">
221
+ <nr-input
222
+ size="small"
223
+ .placeholder=${DEFAULT_SEARCH_PLACEHOLDER}
224
+ .value=${this.searchQuery}
225
+ @nr-input=${this.handleSearchInput}
226
+ autocomplete="off"
227
+ >
228
+ <nr-icon slot="addon-before" name="search"></nr-icon>
229
+ </nr-input>
230
+ </div>
231
+ `
232
+ : nothing}
233
+ <div class="icons-grid-container">
234
+ <lit-virtualizer
235
+ .items=${visibleIcons}
236
+ .layout=${grid({ itemSize: '40px' })}
237
+ .renderItem=${((icon) => html `
238
+ <div
239
+ class=${classMap({
240
+ 'icon-item': true,
241
+ 'selected': this.selectionController.isSelected(icon)
242
+ })}
243
+ @click=${() => this.handleIconSelect(icon)}
244
+ tabindex="0"
245
+ role="button"
246
+ aria-label="Select ${icon.name} icon"
247
+ >
248
+ <nr-icon .name=${icon.name}></nr-icon>
249
+ </div>
250
+ `)}
251
+ ></lit-virtualizer>
252
+ </div>
253
+ </div>
254
+ `;
255
+ }
256
+ render() {
257
+ return html `
258
+ <nr-dropdown
259
+ .open=${this.dropdownOpen}
260
+ trigger="manual"
261
+ .placement=${this.placement}
262
+ .closeOnOutsideClick=${true}
263
+ .closeOnEscape=${true}
264
+ @nr-dropdown-open=${this.handleDropdownOpen}
265
+ @nr-dropdown-close=${this.handleDropdownClose}
266
+ style=${styleMap({
267
+ '--dropdown-width': 'var(--icon-picker-dropdown-width)',
268
+ '--dropdown-max-height': 'var(--icon-picker-dropdown-max-height)'
269
+ })}
270
+ >
271
+ <div slot="trigger" class="trigger-container">
272
+ ${this.renderTrigger()}
273
+ </div>
274
+ <div slot="content">
275
+ ${this.renderIconGrid()}
276
+ </div>
277
+ </nr-dropdown>
278
+ `;
279
+ }
280
+ };
281
+ NrIconPickerElement.styles = styles;
282
+ __decorate([
283
+ property({ type: String, reflect: true })
284
+ ], NrIconPickerElement.prototype, "value", void 0);
285
+ __decorate([
286
+ property({ type: String, reflect: true })
287
+ ], NrIconPickerElement.prototype, "size", void 0);
288
+ __decorate([
289
+ property({ type: String })
290
+ ], NrIconPickerElement.prototype, "placement", void 0);
291
+ __decorate([
292
+ property({ type: String })
293
+ ], NrIconPickerElement.prototype, "trigger", void 0);
294
+ __decorate([
295
+ property({ type: Boolean, reflect: true })
296
+ ], NrIconPickerElement.prototype, "disabled", void 0);
297
+ __decorate([
298
+ property({ type: Boolean })
299
+ ], NrIconPickerElement.prototype, "readonly", void 0);
300
+ __decorate([
301
+ property({ type: String })
302
+ ], NrIconPickerElement.prototype, "placeholder", void 0);
303
+ __decorate([
304
+ property({ type: Array })
305
+ ], NrIconPickerElement.prototype, "iconTypes", void 0);
306
+ __decorate([
307
+ property({ type: Boolean, attribute: 'show-search' })
308
+ ], NrIconPickerElement.prototype, "showSearch", void 0);
309
+ __decorate([
310
+ property({ type: Boolean, attribute: 'show-clear' })
311
+ ], NrIconPickerElement.prototype, "showClear", void 0);
312
+ __decorate([
313
+ property({ type: Number, attribute: 'max-visible' })
314
+ ], NrIconPickerElement.prototype, "maxVisible", void 0);
315
+ __decorate([
316
+ state()
317
+ ], NrIconPickerElement.prototype, "dropdownOpen", void 0);
318
+ __decorate([
319
+ state()
320
+ ], NrIconPickerElement.prototype, "allIcons", void 0);
321
+ __decorate([
322
+ state()
323
+ ], NrIconPickerElement.prototype, "filteredIcons", void 0);
324
+ __decorate([
325
+ state()
326
+ ], NrIconPickerElement.prototype, "searchQuery", void 0);
327
+ __decorate([
328
+ state()
329
+ ], NrIconPickerElement.prototype, "selectedIcon", void 0);
330
+ __decorate([
331
+ state()
332
+ ], NrIconPickerElement.prototype, "isLoading", void 0);
333
+ NrIconPickerElement = __decorate([
334
+ customElement('nr-icon-picker')
335
+ ], NrIconPickerElement);
336
+ export { NrIconPickerElement };
337
+ //# sourceMappingURL=icon-picker.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-picker.component.js","sourceRoot":"","sources":["../../../../src/components/iconpicker/icon-picker.component.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;;;;;;AAEH,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,uCAAuC,CAAC;AAE7D,6BAA6B;AAC7B,OAAO,mCAAmC,CAAC;AAC3C,OAAO,6BAA6B,CAAC;AACrC,OAAO,2BAA2B,CAAC;AACnC,OAAO,+BAA+B,CAAC;AAEvC,0BAA0B;AAC1B,OAAO,MAAM,MAAM,wBAAwB,CAAC;AAC5C,OAAO,EAKH,YAAY,EACf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACH,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,qBAAqB;AACrB,OAAO,EACH,6BAA6B,EAC7B,0BAA0B,EAC1B,yBAAyB,EAC5B,MAAM,wBAAwB,CAAC;AAEhC,mBAAmB;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAKnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,iBAAiB,CAAC,UAAU,CAAC;IAA/D;;QAGI,uBAAkB,GAAG,CAAC,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QAElF,cAAc;QACN,wBAAmB,GAAG,IAAI,6BAA6B,CAAC,IAAI,CAAC,CAAC;QAC9D,qBAAgB,GAAG,IAAI,0BAA0B,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QAC/E,oBAAe,GAAG,IAAI,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAE9D,oBAAoB;QACuB,UAAK,GAAG,YAAY,CAAC;QACrB,SAAI,sCAAwB;QAC3C,cAAS,yCAAoC;QAC7C,YAAO,2CAAoC;QAC3B,aAAQ,GAAG,KAAK,CAAC;QAChC,aAAQ,GAAG,KAAK,CAAC;QAClB,gBAAW,GAAG,mBAAmB,CAAC;QACnC,cAAS,GAAe,8BAAgB,CAAC;QACb,eAAU,GAAG,IAAI,CAAC;QACnB,cAAS,GAAG,IAAI,CAAC;QACjB,eAAU,GAAG,GAAG,CAAC;QAEvE,iBAAiB;QACR,iBAAY,GAAG,KAAK,CAAC;QACrB,aAAQ,GAAqB,EAAE,CAAC;QAChC,kBAAa,GAAqB,EAAE,CAAC;QACrC,gBAAW,GAAG,YAAY,CAAC;QAC3B,iBAAY,GAA0B,IAAI,CAAC;QAC3C,cAAS,GAAG,KAAK,CAAC;IA0M7B,CAAC;IAxMU,iBAAiB;QACxB,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED;;OAEG;IACK,SAAS;QACf,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1D,IAAI,CAAC,aAAa,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YAExC,yCAAyC;YACzC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;YACnF,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,IAAoB;QACnC,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,CAAc;QACtC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAC7B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,CAAQ;QAC1B,CAAC,CAAC,eAAe,EAAE,CAAC;QACpB,IAAI,CAAC,mBAAmB,CAAC,cAAc,EAAE,CAAC;QAC1C,IAAI,CAAC,eAAe,CAAC,kBAAkB,EAAE,CAAC;QAC1C,IAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACK,kBAAkB;QACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,CAAC;IAC3C,CAAC;IAED;;OAEG;IACK,mBAAmB;QACzB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC;QACpC,IAAI,CAAC,eAAe,CAAC,kBAAkB,EAAE,CAAC;IAC5C,CAAC;IAED;;OAEG;IACK,cAAc;QACpB,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,aAAa;QACnB,OAAO,IAAI,CAAA;;;oBAGK,IAAI,CAAC,QAAQ;eAClB,IAAI,CAAC,IAAI;iBACP,IAAI,CAAC,cAAc;;UAE1B,IAAI,CAAC,YAAY;YACjB,CAAC,CAAC,IAAI,CAAA;oDACoC,IAAI,CAAC,YAAY,CAAC,IAAI;wCAClC,IAAI,CAAC,YAAY,CAAC,IAAI;aACjD;YACH,CAAC,CAAC,IAAI,CAAA,6BAA6B,IAAI,CAAC,WAAW,SACrD;UACE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,YAAY;YACnC,CAAC,CAAC,IAAI,CAAA;;;yBAGS,IAAI,CAAC,WAAW;;;aAG5B;YACH,CAAC,CAAC,OACJ;;KAEH,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,cAAc;QACpB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,IAAI,CAAA;;;;;OAKV,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,IAAI,CAAA;;;uCAGsB,qBAAqB;;OAErD,CAAC;QACJ,CAAC;QAED,sCAAsC;QACtC,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAElE,OAAO,IAAI,CAAA;;UAEL,IAAI,CAAC,UAAU;YACf,CAAC,CAAC,IAAI,CAAA;;;;iCAIiB,0BAA0B;2BAChC,IAAI,CAAC,WAAW;8BACb,IAAI,CAAC,iBAAiB;;;;;;aAMvC;YACH,CAAC,CAAC,OACJ;;;qBAGa,YAAY;sBACX,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;0BACtB,CAAC,CAAC,IAAoB,EAAE,EAAE,CAAC,IAAI,CAAA;;wBAEjC,QAAQ,CAAC;YACf,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,IAAI,CAAC;SACtD,CAAC;yBACO,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;;;qCAGrB,IAAI,CAAC,IAAI;;iCAEb,IAAI,CAAC,IAAI;;aAE7B,CAAQ;;;;KAIhB,CAAC;IACJ,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;;gBAEC,IAAI,CAAC,YAAY;;qBAEZ,IAAI,CAAC,SAAgB;+BACX,IAAI;yBACV,IAAI;4BACD,IAAI,CAAC,kBAAkB;6BACtB,IAAI,CAAC,mBAAmB;gBACrC,QAAQ,CAAC;YACf,kBAAkB,EAAE,mCAAmC;YACvD,uBAAuB,EAAE,wCAAwC;SAClE,CAAC;;;YAGE,IAAI,CAAC,aAAa,EAAE;;;YAGpB,IAAI,CAAC,cAAc,EAAE;;;KAG5B,CAAC;IACJ,CAAC;;AArOe,0BAAM,GAAG,MAAM,AAAT,CAAU;AAUW;IAA1C,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;kDAAsB;AACrB;IAA1C,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iDAA6B;AAC3C;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;sDAA8C;AAC7C;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oDAA4C;AAC3B;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;qDAAkB;AAChC;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;qDAAkB;AAClB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wDAAmC;AACnC;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;sDAA0C;AACb;IAAtD,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;uDAAmB;AACnB;IAArD,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;sDAAkB;AACjB;IAArD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;uDAAkB;AAG9D;IAAR,KAAK,EAAE;yDAAsB;AACrB;IAAR,KAAK,EAAE;qDAAiC;AAChC;IAAR,KAAK,EAAE;0DAAsC;AACrC;IAAR,KAAK,EAAE;wDAA4B;AAC3B;IAAR,KAAK,EAAE;yDAA4C;AAC3C;IAAR,KAAK,EAAE;sDAAmB;AA7BhB,mBAAmB;IAD/B,aAAa,CAAC,gBAAgB,CAAC;GACnB,mBAAmB,CAuO/B","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { NuralyUIBaseMixin } from '@nuralyui/common/mixins';\nimport '@lit-labs/virtualizer';\nimport { grid } from '@lit-labs/virtualizer/layouts/grid.js';\n\n// Import required components\nimport '../dropdown/dropdown.component.js';\nimport '../input/input.component.js';\nimport '../icon/icon.component.js';\nimport '../button/button.component.js';\n\n// Import styles and types\nimport styles from './icon-picker.style.js';\nimport {\n IconPickerSize,\n IconPickerPlacement,\n IconPickerTrigger,\n IconType,\n EMPTY_STRING\n} from './icon-picker.types.js';\nimport type { IconPickerIcon } from './icon-picker.types.js';\nimport {\n DEFAULT_PLACEHOLDER,\n DEFAULT_SEARCH_PLACEHOLDER,\n DEFAULT_EMPTY_MESSAGE,\n SEARCH_DEBOUNCE_DELAY\n} from './icon-picker.constant.js';\n\n// Import controllers\nimport {\n IconPickerSelectionController,\n IconPickerSearchController,\n IconPickerEventController\n} from './controllers/index.js';\n\n// Import utilities\nimport { IconLoaderUtils } from './utils/index.js';\n\n// Import interfaces\nimport type { IconPickerHost } from './interfaces/index.js';\n\n/**\n * Advanced icon picker component with search, virtual scrolling, and accessibility.\n * \n * Uses Lucide icons (1500+ beautiful icons) and provides an intuitive selection interface with\n * search filtering, keyboard navigation, and multiple display options.\n * \n * @example\n * ```html\n * <!-- Basic usage -->\n * <nr-icon-picker></nr-icon-picker>\n * \n * <!-- With value -->\n * <nr-icon-picker value=\"heart\"></nr-icon-picker>\n * \n * <!-- Custom configuration -->\n * <nr-icon-picker\n * value=\"star\"\n * size=\"large\"\n * placement=\"top\"\n * show-search\n * show-clear>\n * </nr-icon-picker>\n * ```\n * \n * @fires nr-icon-picker-change - Icon selection changed\n * @fires nr-icon-picker-open - Dropdown opened\n * @fires nr-icon-picker-close - Dropdown closed\n * @fires nr-icon-picker-search - Search query changed\n * @fires nr-icon-picker-clear - Selection cleared\n * \n * @cssproperty --icon-picker-dropdown-width - Width of dropdown\n * @cssproperty --icon-picker-icon-size - Size of icon items\n * @cssproperty --icon-picker-selected-bg - Selected icon background\n * @cssproperty --icon-picker-selected-border - Selected icon border\n */\n@customElement('nr-icon-picker')\nexport class NrIconPickerElement extends NuralyUIBaseMixin(LitElement) implements IconPickerHost {\n static override styles = styles;\n\n override requiredComponents = ['nr-dropdown', 'nr-input', 'nr-icon', 'nr-button'];\n\n // Controllers\n private selectionController = new IconPickerSelectionController(this);\n private searchController = new IconPickerSearchController(this, SEARCH_DEBOUNCE_DELAY);\n private eventController = new IconPickerEventController(this);\n\n // Public properties\n @property({ type: String, reflect: true }) value = EMPTY_STRING;\n @property({ type: String, reflect: true }) size = IconPickerSize.Small;\n @property({ type: String }) placement: string = IconPickerPlacement.Auto;\n @property({ type: String }) trigger: string = IconPickerTrigger.Manual;\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property({ type: Boolean }) readonly = false;\n @property({ type: String }) placeholder = DEFAULT_PLACEHOLDER;\n @property({ type: Array }) iconTypes: IconType[] = [IconType.Solid];\n @property({ type: Boolean, attribute: 'show-search' }) showSearch = true;\n @property({ type: Boolean, attribute: 'show-clear' }) showClear = true;\n @property({ type: Number, attribute: 'max-visible' }) maxVisible = 500;\n\n // Internal state\n @state() dropdownOpen = false;\n @state() allIcons: IconPickerIcon[] = [];\n @state() filteredIcons: IconPickerIcon[] = [];\n @state() searchQuery = EMPTY_STRING;\n @state() selectedIcon: IconPickerIcon | null = null;\n @state() isLoading = false;\n\n override connectedCallback() {\n super.connectedCallback();\n this.loadIcons();\n }\n\n /**\n * Load icons from Lucide library\n */\n private loadIcons(): void {\n this.isLoading = true;\n try {\n this.allIcons = IconLoaderUtils.loadIcons(this.iconTypes);\n this.filteredIcons = [...this.allIcons];\n \n // Set selected icon if value is provided\n if (this.value) {\n this.selectedIcon = this.allIcons.find(icon => icon.name === this.value) || null;\n }\n } catch (error) {\n console.error('Failed to load icons:', error);\n } finally {\n this.isLoading = false;\n }\n }\n\n /**\n * Handle icon selection\n */\n handleIconSelect(icon: IconPickerIcon): void {\n this.selectionController.selectIcon(icon);\n this.eventController.dispatchChangeEvent(icon.name, icon);\n this.dropdownOpen = false;\n }\n\n /**\n * Handle search input\n */\n private handleSearchInput(e: CustomEvent): void {\n const query = e.detail.value;\n this.searchController.search(query);\n this.eventController.dispatchSearchEvent(query);\n }\n\n /**\n * Handle clear button\n */\n private handleClear(e: Event): void {\n e.stopPropagation();\n this.selectionController.clearSelection();\n this.eventController.dispatchClearEvent();\n this.eventController.dispatchChangeEvent(EMPTY_STRING, null);\n }\n\n /**\n * Handle dropdown open\n */\n private handleDropdownOpen(): void {\n this.dropdownOpen = true;\n this.eventController.dispatchOpenEvent();\n }\n\n /**\n * Handle dropdown close\n */\n private handleDropdownClose(): void {\n this.dropdownOpen = false;\n this.searchController.clearSearch();\n this.eventController.dispatchCloseEvent();\n }\n\n /**\n * Toggle dropdown\n */\n private toggleDropdown(): void {\n this.dropdownOpen = !this.dropdownOpen;\n }\n\n /**\n * Render trigger button\n */\n private renderTrigger() {\n return html`\n <nr-button\n class=\"trigger-button\"\n .disabled=${this.disabled}\n size=${this.size}\n @click=${this.toggleDropdown}\n >\n ${this.selectedIcon\n ? html`\n <nr-icon class=\"icon-preview\" .name=${this.selectedIcon.name}></nr-icon>\n <span class=\"icon-name\">${this.selectedIcon.name}</span>\n `\n : html`<span class=\"placeholder\">${this.placeholder}</span>`\n }\n ${this.showClear && this.selectedIcon\n ? html`\n <nr-icon\n name=\"times\"\n @click=${this.handleClear}\n style=\"margin-left: auto; cursor: pointer;\"\n ></nr-icon>\n `\n : nothing\n }\n </nr-button>\n `;\n }\n\n /**\n * Render icon grid\n */\n private renderIconGrid() {\n if (this.isLoading) {\n return html`\n <div class=\"loading-state\">\n <nr-icon name=\"spinner\"></nr-icon>\n <div class=\"empty-message\">Loading icons...</div>\n </div>\n `;\n }\n\n if (this.filteredIcons.length === 0) {\n return html`\n <div class=\"empty-state\">\n <nr-icon name=\"search\"></nr-icon>\n <div class=\"empty-message\">${DEFAULT_EMPTY_MESSAGE}</div>\n </div>\n `;\n }\n\n // Limit visible icons for performance\n const visibleIcons = this.filteredIcons.slice(0, this.maxVisible);\n\n return html`\n <div class=\"dropdown-content\">\n ${this.showSearch\n ? html`\n <div class=\"search-container\">\n <nr-input\n size=\"small\"\n .placeholder=${DEFAULT_SEARCH_PLACEHOLDER}\n .value=${this.searchQuery}\n @nr-input=${this.handleSearchInput}\n autocomplete=\"off\"\n >\n <nr-icon slot=\"addon-before\" name=\"search\"></nr-icon>\n </nr-input>\n </div>\n `\n : nothing\n }\n <div class=\"icons-grid-container\">\n <lit-virtualizer\n .items=${visibleIcons}\n .layout=${grid({ itemSize: '40px' })}\n .renderItem=${((icon: IconPickerIcon) => html`\n <div\n class=${classMap({\n 'icon-item': true,\n 'selected': this.selectionController.isSelected(icon)\n })}\n @click=${() => this.handleIconSelect(icon)}\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Select ${icon.name} icon\"\n >\n <nr-icon .name=${icon.name}></nr-icon>\n </div>\n `) as any}\n ></lit-virtualizer>\n </div>\n </div>\n `;\n }\n\n override render() {\n return html`\n <nr-dropdown\n .open=${this.dropdownOpen}\n trigger=\"manual\"\n .placement=${this.placement as any}\n .closeOnOutsideClick=${true}\n .closeOnEscape=${true}\n @nr-dropdown-open=${this.handleDropdownOpen}\n @nr-dropdown-close=${this.handleDropdownClose}\n style=${styleMap({\n '--dropdown-width': 'var(--icon-picker-dropdown-width)',\n '--dropdown-max-height': 'var(--icon-picker-dropdown-max-height)'\n })}\n >\n <div slot=\"trigger\" class=\"trigger-container\">\n ${this.renderTrigger()}\n </div>\n <div slot=\"content\">\n ${this.renderIconGrid()}\n </div>\n </nr-dropdown>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nr-icon-picker': NrIconPickerElement;\n }\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export declare const DEFAULT_PLACEHOLDER = "Select icon";
7
+ export declare const DEFAULT_SEARCH_PLACEHOLDER = "Search icons...";
8
+ export declare const DEFAULT_EMPTY_MESSAGE = "No icons found";
9
+ export declare const DEFAULT_GRID_SIZE = "32px";
10
+ export declare const DEFAULT_MAX_VISIBLE_ICONS = 500;
11
+ export declare const DEFAULT_DROPDOWN_WIDTH = "320px";
12
+ export declare const DEFAULT_DROPDOWN_MAX_HEIGHT = "380px";
13
+ export declare const ICON_CATEGORIES: readonly ["all", "arrow", "communication", "file", "interface", "media", "social", "text", "utility", "business", "design", "shapes"];
14
+ export declare const SEARCH_DEBOUNCE_DELAY = 300;
15
+ //# sourceMappingURL=icon-picker.constant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-picker.constant.d.ts","sourceRoot":"","sources":["../../../../src/components/iconpicker/icon-picker.constant.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AACjD,eAAO,MAAM,0BAA0B,oBAAoB,CAAC;AAC5D,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AACtD,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,sBAAsB,UAAU,CAAC;AAC9C,eAAO,MAAM,2BAA2B,UAAU,CAAC;AAGnD,eAAO,MAAM,eAAe,uIAalB,CAAC;AAGX,eAAO,MAAM,qBAAqB,MAAM,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ // Default configuration
7
+ export const DEFAULT_PLACEHOLDER = 'Select icon';
8
+ export const DEFAULT_SEARCH_PLACEHOLDER = 'Search icons...';
9
+ export const DEFAULT_EMPTY_MESSAGE = 'No icons found';
10
+ export const DEFAULT_GRID_SIZE = '32px';
11
+ export const DEFAULT_MAX_VISIBLE_ICONS = 500;
12
+ export const DEFAULT_DROPDOWN_WIDTH = '320px';
13
+ export const DEFAULT_DROPDOWN_MAX_HEIGHT = '380px';
14
+ // Icon categories
15
+ export const ICON_CATEGORIES = [
16
+ 'all',
17
+ 'arrow',
18
+ 'communication',
19
+ 'file',
20
+ 'interface',
21
+ 'media',
22
+ 'social',
23
+ 'text',
24
+ 'utility',
25
+ 'business',
26
+ 'design',
27
+ 'shapes'
28
+ ];
29
+ // Search debounce delay
30
+ export const SEARCH_DEBOUNCE_DELAY = 300;
31
+ //# sourceMappingURL=icon-picker.constant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-picker.constant.js","sourceRoot":"","sources":["../../../../src/components/iconpicker/icon-picker.constant.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAwB;AACxB,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAC;AACjD,MAAM,CAAC,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;AAC5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,gBAAgB,CAAC;AACtD,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACxC,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAC9C,MAAM,CAAC,MAAM,2BAA2B,GAAG,OAAO,CAAC;AAEnD,kBAAkB;AAClB,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK;IACL,OAAO;IACP,eAAe;IACf,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,MAAM;IACN,SAAS;IACT,UAAU;IACV,QAAQ;IACR,QAAQ;CACA,CAAC;AAEX,wBAAwB;AACxB,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\n// Default configuration\nexport const DEFAULT_PLACEHOLDER = 'Select icon';\nexport const DEFAULT_SEARCH_PLACEHOLDER = 'Search icons...';\nexport const DEFAULT_EMPTY_MESSAGE = 'No icons found';\nexport const DEFAULT_GRID_SIZE = '32px';\nexport const DEFAULT_MAX_VISIBLE_ICONS = 500;\nexport const DEFAULT_DROPDOWN_WIDTH = '320px';\nexport const DEFAULT_DROPDOWN_MAX_HEIGHT = '380px';\n\n// Icon categories\nexport const ICON_CATEGORIES = [\n 'all',\n 'arrow',\n 'communication',\n 'file',\n 'interface',\n 'media',\n 'social',\n 'text',\n 'utility',\n 'business',\n 'design',\n 'shapes'\n] as const;\n\n// Search debounce delay\nexport const SEARCH_DEBOUNCE_DELAY = 300;\n"]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ declare const _default: import("lit").CSSResult;
7
+ export default _default;
8
+ //# sourceMappingURL=icon-picker.style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-picker.style.d.ts","sourceRoot":"","sources":["../../../../src/components/iconpicker/icon-picker.style.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAIH,wBAgNE"}
@@ -0,0 +1,216 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { css } from 'lit';
7
+ export default css `
8
+ :host {
9
+ /* Sizing */
10
+ --icon-picker-trigger-width: 100%;
11
+ --icon-picker-trigger-height: auto;
12
+ --icon-picker-dropdown-width: 320px;
13
+ --icon-picker-dropdown-max-height: 380px;
14
+ --icon-picker-grid-gap: 4px;
15
+ --icon-picker-icon-size: 24px;
16
+ --icon-picker-icon-padding: 8px;
17
+
18
+ /* Colors - Light mode */
19
+ --icon-picker-background: var(--nuraly-background-primary, #ffffff);
20
+ --icon-picker-border: var(--nuraly-border-color, #d0d0d0);
21
+ --icon-picker-text: var(--nuraly-text-primary, #000000);
22
+ --icon-picker-hover-bg: var(--nuraly-background-hover, #f5f5f5);
23
+ --icon-picker-selected-bg: var(--nuraly-primary-light, #e6f7ff);
24
+ --icon-picker-selected-border: var(--nuraly-primary-color, #1890ff);
25
+ --icon-picker-placeholder-color: var(--nuraly-text-secondary, #999999);
26
+
27
+ display: inline-block;
28
+ width: var(--icon-picker-trigger-width);
29
+ position: relative;
30
+ }
31
+
32
+ @media (prefers-color-scheme: dark) {
33
+ :host {
34
+ --icon-picker-background: var(--nuraly-background-primary, #1f1f1f);
35
+ --icon-picker-border: var(--nuraly-border-color, #404040);
36
+ --icon-picker-text: var(--nuraly-text-primary, #ffffff);
37
+ --icon-picker-hover-bg: var(--nuraly-background-hover, #2a2a2a);
38
+ --icon-picker-selected-bg: var(--nuraly-primary-dark, #003a8c);
39
+ --icon-picker-selected-border: var(--nuraly-primary-color, #40a9ff);
40
+ }
41
+ }
42
+
43
+ /* Trigger container */
44
+ .trigger-container {
45
+ width: 100%;
46
+ }
47
+
48
+ .trigger-button {
49
+ width: 100%;
50
+ display: flex;
51
+ align-items: center;
52
+ gap: 8px;
53
+ padding: 0 12px;
54
+ cursor: pointer;
55
+ }
56
+
57
+ /* Icon preview in trigger */
58
+ .icon-preview {
59
+ font-size: 1.1rem;
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ flex-shrink: 0;
64
+ }
65
+
66
+ .icon-name {
67
+ font-size: 0.875rem;
68
+ overflow: hidden;
69
+ text-overflow: ellipsis;
70
+ white-space: nowrap;
71
+ color: var(--icon-picker-text);
72
+ }
73
+
74
+ .placeholder {
75
+ font-size: 0.875rem;
76
+ color: var(--icon-picker-placeholder-color);
77
+ }
78
+
79
+ /* Dropdown content */
80
+ .dropdown-content {
81
+ width: var(--icon-picker-dropdown-width);
82
+ max-height: var(--icon-picker-dropdown-max-height);
83
+ background: var(--icon-picker-background);
84
+ display: flex;
85
+ flex-direction: column;
86
+ overflow: hidden;
87
+ }
88
+
89
+ /* Search container */
90
+ .search-container {
91
+ padding: 12px;
92
+ background: var(--icon-picker-background);
93
+ border-bottom: 1px solid var(--icon-picker-border);
94
+ flex-shrink: 0;
95
+ z-index: 10;
96
+ }
97
+
98
+ /* Icons grid container */
99
+ .icons-grid-container {
100
+ flex: 1;
101
+ min-height: 0;
102
+ overflow: auto;
103
+ padding: 8px;
104
+ background: var(--icon-picker-background);
105
+ }
106
+
107
+ /* Icon grid using lit-virtualizer */
108
+ .icons-grid {
109
+ display: grid;
110
+ grid-template-columns: repeat(auto-fill, minmax(var(--icon-picker-grid-gap), 1fr));
111
+ gap: var(--icon-picker-grid-gap);
112
+ }
113
+
114
+ /* Individual icon item */
115
+ .icon-item {
116
+ display: flex;
117
+ align-items: center;
118
+ justify-content: center;
119
+ padding: var(--icon-picker-icon-padding);
120
+ cursor: pointer;
121
+ border-radius: 4px;
122
+ border: 2px solid transparent;
123
+ transition: all 0.2s ease;
124
+ min-width: var(--icon-picker-icon-size);
125
+ min-height: var(--icon-picker-icon-size);
126
+ }
127
+
128
+ .icon-item:hover {
129
+ background-color: var(--icon-picker-hover-bg);
130
+ }
131
+
132
+ .icon-item.selected {
133
+ background-color: var(--icon-picker-selected-bg);
134
+ border-color: var(--icon-picker-selected-border);
135
+ }
136
+
137
+ .icon-item:focus {
138
+ outline: 2px solid var(--icon-picker-selected-border);
139
+ outline-offset: 2px;
140
+ }
141
+
142
+ .icon-item nr-icon {
143
+ font-size: var(--icon-picker-icon-size);
144
+ color: var(--icon-picker-text);
145
+ }
146
+
147
+ /* Empty state */
148
+ .empty-state {
149
+ padding: 40px 20px;
150
+ text-align: center;
151
+ color: var(--icon-picker-placeholder-color);
152
+ }
153
+
154
+ .empty-state nr-icon {
155
+ font-size: 48px;
156
+ margin-bottom: 12px;
157
+ opacity: 0.5;
158
+ }
159
+
160
+ .empty-message {
161
+ font-size: 0.875rem;
162
+ }
163
+
164
+ /* Loading state */
165
+ .loading-state {
166
+ padding: 40px 20px;
167
+ text-align: center;
168
+ color: var(--icon-picker-placeholder-color);
169
+ }
170
+
171
+ /* Disabled state */
172
+ :host([disabled]) {
173
+ opacity: 0.6;
174
+ pointer-events: none;
175
+ }
176
+
177
+ /* Size variants */
178
+ :host([size="small"]) {
179
+ --icon-picker-icon-size: 20px;
180
+ --icon-picker-icon-padding: 6px;
181
+ --icon-picker-dropdown-width: 280px;
182
+ }
183
+
184
+ :host([size="large"]) {
185
+ --icon-picker-icon-size: 28px;
186
+ --icon-picker-icon-padding: 10px;
187
+ --icon-picker-dropdown-width: 360px;
188
+ }
189
+
190
+ /* Accessibility */
191
+ @media (prefers-reduced-motion: reduce) {
192
+ .icon-item {
193
+ transition: none;
194
+ }
195
+ }
196
+
197
+ /* Scrollbar styling */
198
+ .icons-grid-container::-webkit-scrollbar {
199
+ width: 8px;
200
+ }
201
+
202
+ .icons-grid-container::-webkit-scrollbar-track {
203
+ background: transparent;
204
+ }
205
+
206
+ .icons-grid-container::-webkit-scrollbar-thumb {
207
+ background: var(--icon-picker-border);
208
+ border-radius: 4px;
209
+ }
210
+
211
+ .icons-grid-container::-webkit-scrollbar-thumb:hover {
212
+ background: var(--icon-picker-text);
213
+ opacity: 0.5;
214
+ }
215
+ `;
216
+ //# sourceMappingURL=icon-picker.style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-picker.style.js","sourceRoot":"","sources":["../../../../src/components/iconpicker/icon-picker.style.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgNjB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { css } from 'lit';\n\nexport default css`\n :host {\n /* Sizing */\n --icon-picker-trigger-width: 100%;\n --icon-picker-trigger-height: auto;\n --icon-picker-dropdown-width: 320px;\n --icon-picker-dropdown-max-height: 380px;\n --icon-picker-grid-gap: 4px;\n --icon-picker-icon-size: 24px;\n --icon-picker-icon-padding: 8px;\n \n /* Colors - Light mode */\n --icon-picker-background: var(--nuraly-background-primary, #ffffff);\n --icon-picker-border: var(--nuraly-border-color, #d0d0d0);\n --icon-picker-text: var(--nuraly-text-primary, #000000);\n --icon-picker-hover-bg: var(--nuraly-background-hover, #f5f5f5);\n --icon-picker-selected-bg: var(--nuraly-primary-light, #e6f7ff);\n --icon-picker-selected-border: var(--nuraly-primary-color, #1890ff);\n --icon-picker-placeholder-color: var(--nuraly-text-secondary, #999999);\n \n display: inline-block;\n width: var(--icon-picker-trigger-width);\n position: relative;\n }\n\n @media (prefers-color-scheme: dark) {\n :host {\n --icon-picker-background: var(--nuraly-background-primary, #1f1f1f);\n --icon-picker-border: var(--nuraly-border-color, #404040);\n --icon-picker-text: var(--nuraly-text-primary, #ffffff);\n --icon-picker-hover-bg: var(--nuraly-background-hover, #2a2a2a);\n --icon-picker-selected-bg: var(--nuraly-primary-dark, #003a8c);\n --icon-picker-selected-border: var(--nuraly-primary-color, #40a9ff);\n }\n }\n\n /* Trigger container */\n .trigger-container {\n width: 100%;\n }\n\n .trigger-button {\n width: 100%;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 12px;\n cursor: pointer;\n }\n\n /* Icon preview in trigger */\n .icon-preview {\n font-size: 1.1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .icon-name {\n font-size: 0.875rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--icon-picker-text);\n }\n\n .placeholder {\n font-size: 0.875rem;\n color: var(--icon-picker-placeholder-color);\n }\n\n /* Dropdown content */\n .dropdown-content {\n width: var(--icon-picker-dropdown-width);\n max-height: var(--icon-picker-dropdown-max-height);\n background: var(--icon-picker-background);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* Search container */\n .search-container {\n padding: 12px;\n background: var(--icon-picker-background);\n border-bottom: 1px solid var(--icon-picker-border);\n flex-shrink: 0;\n z-index: 10;\n }\n\n /* Icons grid container */\n .icons-grid-container {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 8px;\n background: var(--icon-picker-background);\n }\n\n /* Icon grid using lit-virtualizer */\n .icons-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(var(--icon-picker-grid-gap), 1fr));\n gap: var(--icon-picker-grid-gap);\n }\n\n /* Individual icon item */\n .icon-item {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--icon-picker-icon-padding);\n cursor: pointer;\n border-radius: 4px;\n border: 2px solid transparent;\n transition: all 0.2s ease;\n min-width: var(--icon-picker-icon-size);\n min-height: var(--icon-picker-icon-size);\n }\n\n .icon-item:hover {\n background-color: var(--icon-picker-hover-bg);\n }\n\n .icon-item.selected {\n background-color: var(--icon-picker-selected-bg);\n border-color: var(--icon-picker-selected-border);\n }\n\n .icon-item:focus {\n outline: 2px solid var(--icon-picker-selected-border);\n outline-offset: 2px;\n }\n\n .icon-item nr-icon {\n font-size: var(--icon-picker-icon-size);\n color: var(--icon-picker-text);\n }\n\n /* Empty state */\n .empty-state {\n padding: 40px 20px;\n text-align: center;\n color: var(--icon-picker-placeholder-color);\n }\n\n .empty-state nr-icon {\n font-size: 48px;\n margin-bottom: 12px;\n opacity: 0.5;\n }\n\n .empty-message {\n font-size: 0.875rem;\n }\n\n /* Loading state */\n .loading-state {\n padding: 40px 20px;\n text-align: center;\n color: var(--icon-picker-placeholder-color);\n }\n\n /* Disabled state */\n :host([disabled]) {\n opacity: 0.6;\n pointer-events: none;\n }\n\n /* Size variants */\n :host([size=\"small\"]) {\n --icon-picker-icon-size: 20px;\n --icon-picker-icon-padding: 6px;\n --icon-picker-dropdown-width: 280px;\n }\n\n :host([size=\"large\"]) {\n --icon-picker-icon-size: 28px;\n --icon-picker-icon-padding: 10px;\n --icon-picker-dropdown-width: 360px;\n }\n\n /* Accessibility */\n @media (prefers-reduced-motion: reduce) {\n .icon-item {\n transition: none;\n }\n }\n\n /* Scrollbar styling */\n .icons-grid-container::-webkit-scrollbar {\n width: 8px;\n }\n\n .icons-grid-container::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .icons-grid-container::-webkit-scrollbar-thumb {\n background: var(--icon-picker-border);\n border-radius: 4px;\n }\n\n .icons-grid-container::-webkit-scrollbar-thumb:hover {\n background: var(--icon-picker-text);\n opacity: 0.5;\n }\n`;\n"]}