nexa-ui-kit 0.7.1 → 0.7.3

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.
@@ -69,7 +69,7 @@ _sfc_main.render = function(ctx) {
69
69
  "Loading..."
70
70
  ]) : (true) ? h('div', { class: "n-ac-list", role: "listbox", id: listboxId, "data-v-741257a1": "" }, [
71
71
  "\n ",
72
- filteredOptions.value.map((opt, i) =>
72
+ (filteredOptions.value).map((opt, i) =>
73
73
  h('button', { class: ["n-ac-option", { 'is-focused': i === focusedIndex.value }], key: opt.value, type: "button", role: "option", id: instanceId + '-opt-' + i, "aria-selected": (i === focusedIndex.value).toString(), onMouseenter: ($event) => { focusedIndex.value = i }, onClick: ($event) => { selectOption(opt) }, "data-v-741257a1": "" }, [
74
74
  opt.label
75
75
  ])
@@ -27,7 +27,7 @@ const _sfc_main = defineComponent({
27
27
  // Injected render function
28
28
  _sfc_main.render = function(ctx) {
29
29
  const { initials, $slots, label, size, variant, image, shape, Fragment: _ntc_Fragment } = ctx
30
- return h('div', { class: ['n-avatar', `is-${size}`, `is-${variant}`, `is-${shape}`], vBind: true, style: image ? { backgroundImage: `url(${image})` } : {}, "aria-label": label, "data-v-147134": "" }, [
30
+ return h('div', { class: ['n-avatar', `is-${size}`, `is-${variant}`, `is-${shape}`], "vBind:style": "image ? { backgroundImage: `url(${image})` } : {}", "aria-label": label, "data-v-147134": "" }, [
31
31
  "\n ",
32
32
  (!image) ? h('span', { class: "n-avatar-initials", "data-v-147134": "" }, [
33
33
  initials.value
@@ -57,7 +57,7 @@ _sfc_main.render = function(ctx) {
57
57
  ctx.$slots.default ? ctx.$slots.default() : null,
58
58
  "\n "
59
59
  ]) : null,
60
- ripple.value.map((r, index) =>
60
+ (ripple.value).map((r, index) =>
61
61
  h('span', { class: "n-btn-ripple", key: r.id, style: { left: r.x + 'px', top: r.y + 'px' }, "data-v-27fd765": "" })
62
62
  ),
63
63
  "\n "
@@ -48,7 +48,7 @@ _sfc_main.render = function(ctx) {
48
48
  const { resolvedModel, normalize, chips, removeAt, $slots, emit, modelValue, removable, disabled, Fragment: _ntc_Fragment } = ctx
49
49
  return h('div', { class: ["n-chips", { 'is-disabled': disabled }], "data-v-606f06fb": "" }, [
50
50
  "\n ",
51
- chips.value.map((chip, i) =>
51
+ (chips.value).map((chip, i) =>
52
52
  h('div', { class: "n-chip", key: String(chip.value) + ':' + i, "data-v-606f06fb": "" }, [
53
53
  "\n ",
54
54
  h('span', { class: "n-chip-label", "data-v-606f06fb": "" }, [
@@ -186,7 +186,7 @@ _sfc_main.render = function(ctx) {
186
186
  (selectionMode) ? h('th', { class: "n-dt-th is-selection", "data-v-17a3d2ce": "" }, [
187
187
  (selectionMode === 'multiple') ? h('input', { class: "n-dt-selectbox", type: "checkbox", checked: allVisibleSelected.value, onClick: ($event) => { $event.stopPropagation(); (toggleAllVisible)($event) }, "data-v-17a3d2ce": "" }) : null
188
188
  ]) : null,
189
- normalizeColumns.value.map((col, index) =>
189
+ (normalizeColumns.value).map((col, index) =>
190
190
  h('th', { class: ["n-dt-th", [`is-${col.align}`, col.sortable ? 'is-sortable' : '']], key: col.field, style: { width: getWidth(col) || undefined, minWidth: col.minWidth }, "data-field": col.field, onClick: onSortClick, "data-v-17a3d2ce": "" }, [
191
191
  "\n ",
192
192
  h('div', { class: "n-dt-th-content", "data-v-17a3d2ce": "" }, [
@@ -214,7 +214,7 @@ _sfc_main.render = function(ctx) {
214
214
  "\n ",
215
215
  (filterDisplay === 'row') ? h('tr', { class: "n-dt-filter-row", "data-v-17a3d2ce": "" }, [
216
216
  (selectionMode) ? h('th', { class: "n-dt-th is-selection", "data-v-17a3d2ce": "" }) : null,
217
- normalizeColumns.value.map((col, index) =>
217
+ (normalizeColumns.value).map((col, index) =>
218
218
  h('th', { class: ["n-dt-th", `is-${col.align}`], key: col.field, style: { width: getWidth(col) || undefined, minWidth: col.minWidth }, "data-v-17a3d2ce": "" }, [
219
219
  (col.filterable) ? h('input', { class: "n-dt-filter", "data-field": col.field, value: (effectiveFilters.value[col.field]?.value) || '', placeholder: "Filter", onInput: onColumnFilterInput, "data-v-17a3d2ce": "" }) : null
220
220
  ])
@@ -224,13 +224,13 @@ _sfc_main.render = function(ctx) {
224
224
  "\n ",
225
225
  h('tbody', { class: "n-dt-tbody", "data-v-17a3d2ce": "" }, [
226
226
  "\n ",
227
- visibleRows.value.map((row, i) =>
227
+ (visibleRows.value).map((row, i) =>
228
228
  h('tr', { class: ["n-dt-row", { 'is-selected': isRowSelected(row, i + internalFirst.value) }], key: getRowKey(row, i + internalFirst.value), onClick: ($event) => { toggleRowSelection(row, i + internalFirst.value) }, "data-v-17a3d2ce": "" }, [
229
229
  "\n ",
230
230
  (selectionMode) ? h('td', { class: "n-dt-td is-selection", "data-v-17a3d2ce": "" }, [
231
231
  h('input', { class: "n-dt-selectbox", type: "checkbox", checked: isRowSelected(row, i + internalFirst.value), onClick: ($event) => { $event.stopPropagation(); (($event) => { toggleRowSelection(row, i + internalFirst.value) })($event) }, "data-v-17a3d2ce": "" })
232
232
  ]) : null,
233
- normalizeColumns.value.map((col, index) =>
233
+ (normalizeColumns.value).map((col, index) =>
234
234
  h('td', { class: ["n-dt-td", `is-${col.align}`], key: col.field, style: { width: getWidth(col) || undefined, minWidth: col.minWidth }, "data-v-17a3d2ce": "" }, [
235
235
  "\n ",
236
236
  $slots.value && $slots.value[`body-${col.field}`] ? $slots[`body-${col.field}`]({ data: row, column: col, index: i + internalFirst.value }) : getCellContent(row, col, i + internalFirst.value),
@@ -210,13 +210,13 @@ _sfc_main.render = function(ctx) {
210
210
  "\n\n ",
211
211
  h('div', { class: "n-datepicker-grid", "data-v-69fa2c78": "" }, [
212
212
  "\n ",
213
- dayNames.map((d, index) =>
213
+ (dayNames).map((d, index) =>
214
214
  h('div', { class: "n-datepicker-day-header", key: d, "data-v-69fa2c78": "" }, [
215
215
  d
216
216
  ])
217
217
  ),
218
218
  "\n ",
219
- calendarDays.value.map((day, i) =>
219
+ (calendarDays.value).map((day, i) =>
220
220
  h('div', { class: {
221
221
  'n-datepicker-day': true,
222
222
  'is-empty': day === null,
@@ -1,7 +1,7 @@
1
1
  import { signal, effect, onMounted, onUnmounted, h, hText, defineComponent, registerComponent, reloadComponent, injectStyle, Teleport } from 'nexa-framework'
2
2
 
3
3
  const _sfc_main = defineComponent({
4
- __scopeId: 'data-v-39fa634f',
4
+ __scopeId: 'data-v-655f39d1',
5
5
  __hmrId: 'NModal_nexa',
6
6
  props: {
7
7
  show: { type: Boolean, default: false },
@@ -17,6 +17,7 @@ const _sfc_main = defineComponent({
17
17
  let modalEl = null
18
18
  let previousFocus = null
19
19
  const bodyOverflow = signal('')
20
+ const setModalRef = (el) => { modalEl = el }
20
21
  const sizeMap = { sm: '400px', md: '500px', lg: '640px', xl: '800px', full: '96%' }
21
22
  effect(() => {
22
23
  if (props.show) {
@@ -72,40 +73,40 @@ const _sfc_main = defineComponent({
72
73
  window.removeEventListener('keydown', handleEsc)
73
74
  document.body.style.overflow = ''
74
75
  })
75
- return { isVisible, modalEl, previousFocus, bodyOverflow, sizeMap, close, handleEsc, handleOverlayClick, focusableSelector, handleKeydown, $slots, emit }
76
+ return { isVisible, modalEl, previousFocus, bodyOverflow, setModalRef, sizeMap, close, handleEsc, handleOverlayClick, focusableSelector, handleKeydown, $slots, emit }
76
77
  }
77
78
  })
78
79
  // Injected render function
79
80
  _sfc_main.render = function(ctx) {
80
- const { isVisible, modalEl, previousFocus, bodyOverflow, sizeMap, close, handleEsc, handleOverlayClick, focusableSelector, handleKeydown, $slots, emit, show, title, size, closable, closeLeft, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
81
- return h(_ntc_Teleport, { to: "body", "data-v-39fa634f": "" }, [
81
+ const { isVisible, modalEl, previousFocus, bodyOverflow, setModalRef, sizeMap, close, handleEsc, handleOverlayClick, focusableSelector, handleKeydown, $slots, emit, show, title, size, closable, closeLeft, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
82
+ return h(_ntc_Teleport, { to: "body", "data-v-655f39d1": "" }, [
82
83
  "\n ",
83
- (isVisible.value) ? h('div', { class: "n-modal-root", "data-v-39fa634f": "" }, [
84
+ (isVisible.value) ? h('div', { class: "n-modal-root", "data-v-655f39d1": "" }, [
84
85
  "\n ",
85
- h('div', { class: ["n-modal-overlay", { 'is-active': show }], onClick: handleOverlayClick, "data-v-39fa634f": "" }),
86
+ h('div', { class: ["n-modal-overlay", { 'is-active': show }], onClick: handleOverlayClick, "data-v-655f39d1": "" }),
86
87
  "\n ",
87
- h('div', { class: ["n-modal-container", { 'is-active': show }], ref: "modalEl", style: { maxWidth: sizeMap[size] || size }, tabindex: "-1", onKeydown: handleKeydown, "data-v-39fa634f": "" }, [
88
+ h('div', { class: ["n-modal-container", { 'is-active': show }], ref: setModalRef, style: { maxWidth: sizeMap[size] || size }, tabindex: "-1", onKeydown: handleKeydown, "data-v-655f39d1": "" }, [
88
89
  "\n ",
89
- (title || $slots.header) ? h('div', { class: ["n-modal-header", { 'close-left': closeLeft }], "data-v-39fa634f": "" }, [
90
+ (title || $slots.header) ? h('div', { class: ["n-modal-header", { 'close-left': closeLeft }], "data-v-655f39d1": "" }, [
90
91
  "\n ",
91
- (closable && closeLeft) ? h('button', { class: "n-modal-close", onClick: close, "aria-label": "Close", "data-v-39fa634f": "" }, [
92
+ (closable && closeLeft) ? h('button', { class: "n-modal-close", onClick: close, "aria-label": "Close", "data-v-655f39d1": "" }, [
92
93
  "×"
93
94
  ]) : null,
94
95
  ctx.$slots.header ? ctx.$slots.header() : ["\n ", h('h3', null, [
95
96
  title
96
97
  ]), "\n "],
97
98
  "\n ",
98
- (closable && !closeLeft) ? h('button', { class: "n-modal-close", onClick: close, "aria-label": "Close", "data-v-39fa634f": "" }, [
99
+ (closable && !closeLeft) ? h('button', { class: "n-modal-close", onClick: close, "aria-label": "Close", "data-v-655f39d1": "" }, [
99
100
  "×"
100
101
  ]) : null
101
102
  ]) : null,
102
- h('div', { class: "n-modal-content", "data-v-39fa634f": "" }, [
103
+ h('div', { class: "n-modal-content", "data-v-655f39d1": "" }, [
103
104
  "\n ",
104
105
  ctx.$slots.default ? ctx.$slots.default() : null,
105
106
  "\n "
106
107
  ]),
107
108
  "\n ",
108
- ($slots.footer) ? h('div', { class: "n-modal-footer", "data-v-39fa634f": "" }, [
109
+ ($slots.footer) ? h('div', { class: "n-modal-footer", "data-v-655f39d1": "" }, [
109
110
  "\n ",
110
111
  ctx.$slots.footer ? ctx.$slots.footer() : null,
111
112
  "\n "
@@ -115,12 +116,12 @@ _sfc_main.render = function(ctx) {
115
116
  ]) : null
116
117
  ])
117
118
  }
118
- _sfc_main.__scopeId = 'data-v-39fa634f'
119
+ _sfc_main.__scopeId = 'data-v-655f39d1'
119
120
  _sfc_main.__hmrId = 'NModal_nexa'
120
121
 
121
122
  export default _sfc_main
122
123
 
123
- const __style = `.n-modal-root[data-v-39fa634f]{
124
+ const __style = `.n-modal-root[data-v-655f39d1]{
124
125
  position: fixed;
125
126
  top: 0;
126
127
  left: 0;
@@ -132,7 +133,7 @@ const __style = `.n-modal-root[data-v-39fa634f]{
132
133
  z-index: var(--n-z-modal);
133
134
  }
134
135
 
135
- .n-modal-overlay[data-v-39fa634f]{
136
+ .n-modal-overlay[data-v-655f39d1]{
136
137
  position: absolute;
137
138
  top: 0;
138
139
  left: 0;
@@ -144,11 +145,11 @@ const __style = `.n-modal-root[data-v-39fa634f]{
144
145
  transition: opacity 0.25s ease;
145
146
  }
146
147
 
147
- .n-modal-overlay.is-active[data-v-39fa634f]{
148
+ .n-modal-overlay.is-active[data-v-655f39d1]{
148
149
  opacity: 1;
149
150
  }
150
151
 
151
- .n-modal-container[data-v-39fa634f]{
152
+ .n-modal-container[data-v-655f39d1]{
152
153
  position: relative;
153
154
  width: 90%;
154
155
  background: var(--n-color-surface);
@@ -165,12 +166,12 @@ const __style = `.n-modal-root[data-v-39fa634f]{
165
166
  flex-direction: column;
166
167
  }
167
168
 
168
- .n-modal-container.is-active[data-v-39fa634f]{
169
+ .n-modal-container.is-active[data-v-655f39d1]{
169
170
  transform: scale(1) translateY(0);
170
171
  opacity: 1;
171
172
  }
172
173
 
173
- .n-modal-header[data-v-39fa634f]{
174
+ .n-modal-header[data-v-655f39d1]{
174
175
  padding: var(--n-space-6) var(--n-space-8);
175
176
  border-bottom: 1px solid var(--n-color-border);
176
177
  display: flex;
@@ -179,14 +180,14 @@ const __style = `.n-modal-root[data-v-39fa634f]{
179
180
  flex-shrink: 0;
180
181
  }
181
182
 
182
- .n-modal-header h3[data-v-39fa634f]{
183
+ .n-modal-header h3[data-v-655f39d1]{
183
184
  margin: 0;
184
185
  font-size: var(--n-text-xl);
185
186
  font-weight: var(--n-weight-bold);
186
187
  color: var(--n-color-text);
187
188
  }
188
189
 
189
- .n-modal-close[data-v-39fa634f]{
190
+ .n-modal-close[data-v-655f39d1]{
190
191
  background: transparent;
191
192
  border: none;
192
193
  color: var(--n-color-text-secondary);
@@ -203,19 +204,19 @@ const __style = `.n-modal-root[data-v-39fa634f]{
203
204
  border-radius: var(--n-radius-sm);
204
205
  }
205
206
 
206
- .n-modal-close[data-v-39fa634f]:hover{
207
+ .n-modal-close[data-v-655f39d1]:hover{
207
208
  color: var(--n-color-text);
208
209
  background: var(--n-color-glass);
209
210
  }
210
211
 
211
- .n-modal-content[data-v-39fa634f]{
212
+ .n-modal-content[data-v-655f39d1]{
212
213
  padding: var(--n-space-8);
213
214
  color: var(--n-color-text-secondary);
214
215
  overflow-y: auto;
215
216
  flex: 1;
216
217
  }
217
218
 
218
- .n-modal-footer[data-v-39fa634f]{
219
+ .n-modal-footer[data-v-655f39d1]{
219
220
  padding: var(--n-space-5) var(--n-space-8);
220
221
  background: rgba(0, 0, 0, 0.15);
221
222
  border-top: 1px solid var(--n-color-border);
@@ -224,4 +225,4 @@ const __style = `.n-modal-root[data-v-39fa634f]{
224
225
  gap: var(--n-space-4);
225
226
  flex-shrink: 0;
226
227
  }`
227
- injectStyle('data-v-39fa634f', __style)
228
+ injectStyle('data-v-655f39d1', __style)
@@ -16,6 +16,8 @@ let modalEl = null
16
16
  let previousFocus = null
17
17
  const bodyOverflow = signal('')
18
18
 
19
+ const setModalRef = (el) => { modalEl = el }
20
+
19
21
  const sizeMap = { sm: '400px', md: '500px', lg: '640px', xl: '800px', full: '96%' }
20
22
 
21
23
  effect(() => {
@@ -90,7 +92,7 @@ onUnmounted(() => {
90
92
  @click="handleOverlayClick"
91
93
  ></div>
92
94
  <div
93
- ref="modalEl"
95
+ :ref="setModalRef"
94
96
  class="n-modal-container"
95
97
  :class="{ 'is-active': show }"
96
98
  :style="{ maxWidth: sizeMap[size] || size }"
@@ -73,7 +73,7 @@ _sfc_main.render = function(ctx) {
73
73
  h('div', { class: "n-ms-trigger", role: "combobox", tabindex: "0", "aria-expanded": isOpen.value, onClick: toggleOpen, onKeydown: onKeydown, "data-v-12b3b8c4": "" }, [
74
74
  "\n ",
75
75
  (selectedLabels.value.length > 0) ? h('div', { class: "n-ms-chips", "data-v-12b3b8c4": "" }, [
76
- selectedLabels.value.slice(0, maxChips).map((c, index) =>
76
+ (selectedLabels.value.slice(0, maxChips)).map((c, index) =>
77
77
  h('div', { class: "n-ms-chip", key: String(c.value), "data-v-12b3b8c4": "" }, [
78
78
  h('span', { class: "n-ms-chip-label", "data-v-12b3b8c4": "" }, [
79
79
  c.label
@@ -107,7 +107,7 @@ _sfc_main.render = function(ctx) {
107
107
  h('input', { class: "n-ms-search-input", value: queryDraft.value, placeholder: "Search...", onInput: onSearchInput, onKeydown: ($event) => { $event.stopPropagation(); (onKeydown)($event) }, "data-v-12b3b8c4": "" })
108
108
  ]) : null,
109
109
  h('div', { class: "n-ms-options", "data-v-12b3b8c4": "" }, [
110
- filteredOptions.value.map((opt, i) =>
110
+ (filteredOptions.value).map((opt, i) =>
111
111
  h('button', { class: ["n-ms-option", { 'is-selected': selectedSet.value.has(opt.value), 'is-focused': i === focusedIndex.value, 'is-disabled': opt.disabled }], key: String(opt.value) + ':' + i, type: "button", "data-ms-opt": String(opt.value), disabled: opt.disabled, onMouseenter: ($event) => { focusedIndex.value = i }, onClick: ($event) => { toggleValue(opt.value) }, "data-v-12b3b8c4": "" }, [
112
112
  h('span', { class: "n-ms-check", "data-v-12b3b8c4": "" }, [
113
113
  selectedSet.value.has(opt.value) ? '✓' : ''
@@ -128,7 +128,7 @@ _sfc_main.render = function(ctx) {
128
128
  h('input', { class: "n-ms-search-input", value: queryDraft.value, placeholder: "Search...", onInput: onSearchInput, onKeydown: ($event) => { $event.stopPropagation(); (onKeydown)($event) }, "data-v-12b3b8c4": "" })
129
129
  ]) : null,
130
130
  h('div', { class: "n-ms-options", "data-v-12b3b8c4": "" }, [
131
- filteredOptions.value.map((opt, i) =>
131
+ (filteredOptions.value).map((opt, i) =>
132
132
  h('button', { class: ["n-ms-option", { 'is-selected': selectedSet.value.has(opt.value), 'is-focused': i === focusedIndex.value, 'is-disabled': opt.disabled }], key: String(opt.value) + ':' + i, type: "button", "data-ms-opt": String(opt.value), disabled: opt.disabled, onMouseenter: ($event) => { focusedIndex.value = i }, onClick: ($event) => { toggleValue(opt.value) }, "data-v-12b3b8c4": "" }, [
133
133
  h('span', { class: "n-ms-check", "data-v-12b3b8c4": "" }, [
134
134
  selectedSet.value.has(opt.value) ? '✓' : ''
@@ -96,7 +96,7 @@ _sfc_main.render = function(ctx) {
96
96
  "\n ",
97
97
  h('select', { class: "n-pg-select", value: rows, onChange: changeRows, "data-v-372b30ac": "" }, [
98
98
  "\n ",
99
- rowsPerPageOptions.map((n, index) =>
99
+ (rowsPerPageOptions).map((n, index) =>
100
100
  h('option', { key: n, value: n, "data-v-372b30ac": "" }, [
101
101
  n
102
102
  ])
@@ -131,7 +131,7 @@ _sfc_main.render = function(ctx) {
131
131
  "\n ",
132
132
  h('div', { class: "n-password-meter", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 4, "aria-valuenow": strength.value.score, "aria-label": 'Fuerza de contraseña: ' + strength.value.label, "data-v-7b897096": "" }, [
133
133
  "\n ",
134
- [1, 2, 3, 4].map((n, index) =>
134
+ ([1, 2, 3, 4]).map((n, index) =>
135
135
  h('span', { class: ["n-password-meter-seg", { 'is-on': n <= strength.value.score }], key: n, "data-v-7b897096": "" })
136
136
  ),
137
137
  "\n "
@@ -144,7 +144,7 @@ _sfc_main.render = function(ctx) {
144
144
  ]) : null,
145
145
  (showRequirements && validate && modelValue) ? h('ul', { class: "n-password-req", id: inputId.value + '-requirements', "data-v-7b897096": "" }, [
146
146
  "\n ",
147
- requirements.value.map((r, index) =>
147
+ (requirements.value).map((r, index) =>
148
148
  h('li', { class: ["n-password-req-item", { 'is-ok': r.ok }], key: r.key, "data-v-7b897096": "" }, [
149
149
  "\n ",
150
150
  h('span', { class: "n-password-req-icon", "data-v-7b897096": "" }, [
@@ -214,13 +214,13 @@ _sfc_main.render = function(ctx) {
214
214
  ]) : null,
215
215
  h('div', { class: "n-select-options", "data-v-fef169b": "" }, [
216
216
  "\n ",
217
- filteredOptions.value.map((item, i) =>
217
+ (filteredOptions.value).map((item, i) =>
218
218
  h('div', { key: i, "data-v-fef169b": "" }, [
219
219
  "\n ",
220
220
  ('group' in item) ? h('div', { class: "n-select-group-label", "data-v-fef169b": "" }, [
221
221
  item.group
222
222
  ]) : null,
223
- 'items' in item ? item.items : [item].map((opt, index) =>
223
+ ('items' in item ? item.items : [item]).map((opt, index) =>
224
224
  h('div', { class: ["n-select-option", {
225
225
  'is-selected': opt.value === modelValue,
226
226
  'is-focused': getFlatOptions().indexOf(opt) === focusedIndex.value,
@@ -252,13 +252,13 @@ _sfc_main.render = function(ctx) {
252
252
  ]) : null,
253
253
  h('div', { class: "n-select-options", "data-v-fef169b": "" }, [
254
254
  "\n ",
255
- filteredOptions.value.map((item, i) =>
255
+ (filteredOptions.value).map((item, i) =>
256
256
  h('div', { key: i, "data-v-fef169b": "" }, [
257
257
  "\n ",
258
258
  ('group' in item) ? h('div', { class: "n-select-group-label", "data-v-fef169b": "" }, [
259
259
  item.group
260
260
  ]) : null,
261
- 'items' in item ? item.items : [item].map((opt, index) =>
261
+ ('items' in item ? item.items : [item]).map((opt, index) =>
262
262
  h('div', { class: ["n-select-option", {
263
263
  'is-selected': opt.value === modelValue,
264
264
  'is-focused': getFlatOptions().indexOf(opt) === focusedIndex.value,
@@ -1,60 +1,60 @@
1
1
  import { h, hText, effect, defineComponent, registerComponent, reloadComponent, injectStyle } from 'nexa-framework'
2
2
 
3
3
  const _sfc_main = defineComponent({
4
- __scopeId: 'data-v-76b5aa9d',
4
+ __scopeId: 'data-v-6b9116c8',
5
5
  __hmrId: 'NSkeleton_nexa',
6
6
  props: {
7
- variant: { type: String, default: 'text' }, // text, circle, card
7
+ variant: { type: String, default: 'text' },
8
8
  lines: { type: Number, default: 3 },
9
9
  width: { type: String, default: '100%' },
10
10
  height: { type: String, default: '' }
11
11
  },
12
12
  setup(props, setupContext) {
13
13
  const { emit, slots, slots: $slots } = setupContext
14
- return { $slots }
14
+ const lineArray = Array.from({ length: props.lines || 3 }, (_, i) => i + 1)
15
+ return { lineArray, $slots }
15
16
  }
16
17
  })
17
18
  // Injected render function
18
19
  _sfc_main.render = function(ctx) {
19
- const { $slots, variant, // text circle card
20
- lines, width, height, Fragment: _ntc_Fragment } = ctx
21
- return h('div', { class: ["n-skeleton", `is-${variant}`], style: { width, height }, "data-v-76b5aa9d": "" }, [
20
+ const { lineArray, $slots, variant, lines, width, height, Fragment: _ntc_Fragment } = ctx
21
+ return h('div', { class: ["n-skeleton", `is-${variant}`], style: { width, height }, "data-v-6b9116c8": "" }, [
22
22
  "\n ",
23
- (variant === 'text') ? h('div', { class: "n-skeleton-lines", "data-v-76b5aa9d": "" }, [
23
+ (variant === 'text') ? h('div', { class: "n-skeleton-lines", "data-v-6b9116c8": "" }, [
24
24
  "\n ",
25
- lines.map((i, index) =>
26
- h('div', { class: "n-skeleton-line", key: i, style: { width: i === lines ? '60%' : '100%' }, "data-v-76b5aa9d": "" })
25
+ (lineArray).map((n, index) =>
26
+ h('div', { class: "n-skeleton-line", key: n, style: { width: n === lineArray.length ? '60%' : '100%' }, "data-v-6b9116c8": "" })
27
27
  ),
28
28
  "\n "
29
29
  ]) : null,
30
- (variant === 'circle') ? h('div', { class: "n-skeleton-circle", "data-v-76b5aa9d": "" }) : null,
31
- (variant === 'card') ? h('div', { class: "n-skeleton-card", "data-v-76b5aa9d": "" }, [
30
+ (variant === 'circle') ? h('div', { class: "n-skeleton-circle", "data-v-6b9116c8": "" }) : null,
31
+ (variant === 'card') ? h('div', { class: "n-skeleton-card", "data-v-6b9116c8": "" }, [
32
32
  "\n ",
33
- h('div', { class: "n-skeleton-card-image", "data-v-76b5aa9d": "" }),
33
+ h('div', { class: "n-skeleton-card-image", "data-v-6b9116c8": "" }),
34
34
  "\n ",
35
- h('div', { class: "n-skeleton-card-body", "data-v-76b5aa9d": "" }, [
35
+ h('div', { class: "n-skeleton-card-body", "data-v-6b9116c8": "" }, [
36
36
  "\n ",
37
- h('div', { class: "n-skeleton-line", style: "width: 70%", "data-v-76b5aa9d": "" }),
37
+ h('div', { class: "n-skeleton-line", style: "width: 70%", "data-v-6b9116c8": "" }),
38
38
  "\n ",
39
- h('div', { class: "n-skeleton-line", style: "width: 40%", "data-v-76b5aa9d": "" }),
39
+ h('div', { class: "n-skeleton-line", style: "width: 40%", "data-v-6b9116c8": "" }),
40
40
  "\n "
41
41
  ]),
42
42
  "\n "
43
43
  ]) : null
44
44
  ])
45
45
  }
46
- _sfc_main.__scopeId = 'data-v-76b5aa9d'
46
+ _sfc_main.__scopeId = 'data-v-6b9116c8'
47
47
  _sfc_main.__hmrId = 'NSkeleton_nexa'
48
48
 
49
49
  export default _sfc_main
50
50
 
51
- const __style = `.n-skeleton[data-v-76b5aa9d]{
51
+ const __style = `.n-skeleton[data-v-6b9116c8]{
52
52
  display: flex;
53
53
  flex-direction: column;
54
54
  gap: var(--n-space-2);
55
55
  }
56
56
 
57
- .n-skeleton-line[data-v-76b5aa9d]{
57
+ .n-skeleton-line[data-v-6b9116c8]{
58
58
  height: 14px;
59
59
  border-radius: var(--n-radius-sm);
60
60
  background: linear-gradient(90deg, var(--n-color-surface-alt) 25%, var(--n-color-surface-hover) 50%, var(--n-color-surface-alt) 75%);
@@ -62,7 +62,7 @@ const __style = `.n-skeleton[data-v-76b5aa9d]{
62
62
  animation: n-skeleton-shimmer 1.5s ease-in-out infinite;
63
63
  }
64
64
 
65
- .is-circle .n-skeleton-circle[data-v-76b5aa9d]{
65
+ .is-circle .n-skeleton-circle[data-v-6b9116c8]{
66
66
  width: 60px;
67
67
  height: 60px;
68
68
  border-radius: var(--n-radius-full);
@@ -71,13 +71,13 @@ const __style = `.n-skeleton[data-v-76b5aa9d]{
71
71
  animation: n-skeleton-shimmer 1.5s ease-in-out infinite;
72
72
  }
73
73
 
74
- .is-card .n-skeleton-card[data-v-76b5aa9d]{
74
+ .is-card .n-skeleton-card[data-v-6b9116c8]{
75
75
  border-radius: var(--n-radius-lg);
76
76
  overflow: hidden;
77
77
  border: 1px solid var(--n-color-border);
78
78
  }
79
79
 
80
- .is-card .n-skeleton-card-image[data-v-76b5aa9d]{
80
+ .is-card .n-skeleton-card-image[data-v-6b9116c8]{
81
81
  height: 140px;
82
82
  background: linear-gradient(90deg, var(--n-color-surface-alt) 25%, var(--n-color-surface-hover) 50%, var(--n-color-surface-alt) 75%);
83
83
  background-size: 200% 100%;
@@ -92,7 +92,7 @@ const __style = `.n-skeleton[data-v-76b5aa9d]{
92
92
  }
93
93
 
94
94
  @keyframes n-skeleton-shimmer {
95
- from[data-v-76b5aa9d]{ background-position: 200% 0; }
96
- to[data-v-76b5aa9d]{ background-position: -200% 0; }
95
+ from[data-v-6b9116c8]{ background-position: 200% 0; }
96
+ to[data-v-6b9116c8]{ background-position: -200% 0; }
97
97
  }`
98
- injectStyle('data-v-76b5aa9d', __style)
98
+ injectStyle('data-v-6b9116c8', __style)
@@ -1,16 +1,18 @@
1
1
  <script setup>
2
2
  const props = defineProps({
3
- variant: { type: String, default: 'text' }, // text, circle, card
3
+ variant: { type: String, default: 'text' },
4
4
  lines: { type: Number, default: 3 },
5
5
  width: { type: String, default: '100%' },
6
6
  height: { type: String, default: '' }
7
7
  })
8
+
9
+ const lineArray = Array.from({ length: props.lines || 3 }, (_, i) => i + 1)
8
10
  </script>
9
11
 
10
12
  <template>
11
13
  <div class="n-skeleton" :class="`is-${variant}`" :style="{ width, height }">
12
14
  <div v-if="variant === 'text'" class="n-skeleton-lines">
13
- <div v-for="i in lines" :key="i" class="n-skeleton-line" :style="{ width: i === lines ? '60%' : '100%' }"></div>
15
+ <div v-for="n in lineArray" :key="n" class="n-skeleton-line" :style="{ width: n === lineArray.length ? '60%' : '100%' }"></div>
14
16
  </div>
15
17
  <div v-if="variant === 'circle'" class="n-skeleton-circle"></div>
16
18
  <div v-if="variant === 'card'" class="n-skeleton-card">
@@ -27,7 +27,7 @@ _sfc_main.render = function(ctx) {
27
27
  "\n ",
28
28
  h('div', { class: "n-tabs-header", "data-v-339e5ee5": "" }, [
29
29
  "\n ",
30
- tabs.map((tab, index) =>
30
+ (tabs).map((tab, index) =>
31
31
  h('div', { class: ["n-tab", { 'is-active': tab.key === activeKey.value, 'is-disabled': tab.disabled }], key: tab.key, onClick: ($event) => { select(tab.key) }, "data-v-339e5ee5": "" }, [
32
32
  "\n ",
33
33
  (tab.icon) ? h('span', { class: "n-tab-icon", "data-v-339e5ee5": "" }, [
@@ -21,7 +21,7 @@ _sfc_main.render = function(ctx) {
21
21
  "\n ",
22
22
  h('div', { class: ["n-toast-container", positionClass], "data-v-8ac4158": "" }, [
23
23
  "\n ",
24
- toasts.value.map((toast, index) =>
24
+ (toasts.value).map((toast, index) =>
25
25
  h('div', { class: ["n-toast", `is-${toast.type}`], key: toast.id, onClick: ($event) => { remove(toast.id) }, "data-v-8ac4158": "" }, [
26
26
  "\n ",
27
27
  h('div', { class: "n-toast-body", "data-v-8ac4158": "" }, [
@@ -50,7 +50,7 @@ _sfc_main.render = function(ctx) {
50
50
  const { expanded, toggleExpand, selectItem, hasChildren, isExpanded, isSelected, flatTree, toggle, $slots, emit, items, selectable, selected, Fragment: _ntc_Fragment } = ctx
51
51
  return h('div', { class: "n-tree-menu", "data-v-44b3942a": "" }, [
52
52
  "\n ",
53
- flatTree.value.map((item, index) =>
53
+ (flatTree.value).map((item, index) =>
54
54
  h('div', { class: ["n-tree-item", { 'is-selected': isSelected(item.id) }], key: item.id, style: { '--n-tree-depth': String(item._depth) }, "data-v-44b3942a": "" }, [
55
55
  "\n ",
56
56
  h('div', { class: "n-tree-row", onClick: ($event) => { selectItem(item) }, "data-v-44b3942a": "" }, [
@@ -56,7 +56,7 @@ _sfc_main.render = function(ctx) {
56
56
  "\n ",
57
57
  h('div', { class: "n-virtual-list-spacer", style: { height: totalHeight.value + 'px', position: 'relative' }, "data-v-2d5f09ed": "" }, [
58
58
  "\n ",
59
- visibleItems.value.map((row, index) =>
59
+ (visibleItems.value).map((row, index) =>
60
60
  h('div', { class: "n-virtual-list-row", key: keyFn ? keyFn(row.item, row.index) : row.index, style: { position: 'absolute', top: row.top + 'px', width: '100%', height: itemHeight + 'px' }, "data-v-2d5f09ed": "" }, [
61
61
  "\n ",
62
62
  renderItem(row.item, row.index),
@@ -1,21 +1,28 @@
1
1
  import { signal } from 'nexa-framework';
2
- const toasts = signal([]);
3
- let nextId = 1;
2
+ const g = globalThis;
3
+ const GLOBAL_KEY = '__NEXA_TOAST_SERVICE__';
4
+ if (!g[GLOBAL_KEY]) {
5
+ g[GLOBAL_KEY] = {
6
+ toasts: signal([]),
7
+ nextId: 1
8
+ };
9
+ }
10
+ const state = g[GLOBAL_KEY];
4
11
  export const useToast = () => {
5
12
  const add = (message, type = 'info', duration = 3000) => {
6
- const id = nextId++;
13
+ const id = state.nextId++;
7
14
  const toast = { id, message, type, duration };
8
- toasts.value = [...toasts.value, toast];
15
+ state.toasts.value = [...state.toasts.value, toast];
9
16
  if (duration > 0) {
10
17
  setTimeout(() => remove(id), duration);
11
18
  }
12
19
  return id;
13
20
  };
14
21
  const remove = (id) => {
15
- toasts.value = toasts.value.filter((t) => t.id !== id);
22
+ state.toasts.value = state.toasts.value.filter((t) => t.id !== id);
16
23
  };
17
24
  return {
18
- toasts,
25
+ toasts: state.toasts,
19
26
  add,
20
27
  remove,
21
28
  success: (msg, dur) => add(msg, 'success', dur),
@@ -0,0 +1,170 @@
1
+ :root {
2
+ /* ─── Color Palette ─── */
3
+ --n-color-primary: #3b82f6;
4
+ --n-color-primary-hover: #2563eb;
5
+ --n-color-primary-active: #1d4ed8;
6
+ --n-color-primary-light: rgba(59, 130, 246, 0.12);
7
+ --n-color-primary-glow: rgba(59, 130, 246, 0.3);
8
+
9
+ --n-color-success: #10b981;
10
+ --n-color-success-hover: #059669;
11
+ --n-color-success-light: rgba(16, 185, 129, 0.12);
12
+
13
+ --n-color-warning: #f59e0b;
14
+ --n-color-warning-hover: #d97706;
15
+ --n-color-warning-light: rgba(245, 158, 11, 0.12);
16
+
17
+ --n-color-danger: #ef4444;
18
+ --n-color-danger-hover: #dc2626;
19
+ --n-color-danger-light: rgba(239, 68, 68, 0.12);
20
+
21
+ --n-color-info: #06b6d4;
22
+ --n-color-info-hover: #0891b2;
23
+ --n-color-info-light: rgba(6, 182, 212, 0.12);
24
+
25
+ --n-color-surface: #0f172a;
26
+ --n-color-surface-alt: #1e293b;
27
+ --n-color-surface-hover: #334155;
28
+ --n-color-surface-elevated: #1e293b;
29
+
30
+ --n-color-bg: #020617;
31
+ --n-color-bg-alt: #0f172a;
32
+
33
+ --n-color-text: #f8fafc;
34
+ --n-color-text-secondary: #94a3b8;
35
+ --n-color-text-muted: #64748b;
36
+ --n-color-text-inverse: #0f172a;
37
+
38
+ --n-color-border: rgba(255, 255, 255, 0.08);
39
+ --n-color-border-hover: rgba(255, 255, 255, 0.15);
40
+ --n-color-border-active: rgba(255, 255, 255, 0.25);
41
+
42
+ --n-color-overlay: rgba(2, 6, 17, 0.7);
43
+ --n-color-glass: rgba(255, 255, 255, 0.04);
44
+ --n-color-glass-border: rgba(255, 255, 255, 0.08);
45
+ --n-color-glass-hover: rgba(255, 255, 255, 0.08);
46
+
47
+ /* ─── Typography ─── */
48
+ --n-font-sans: 'Outfit', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
49
+ --n-font-mono: 'JetBrains Mono', 'Fira Code', monospace;
50
+
51
+ --n-text-xs: 0.75rem;
52
+ --n-text-sm: 0.875rem;
53
+ --n-text-base: 1rem;
54
+ --n-text-lg: 1.125rem;
55
+ --n-text-xl: 1.25rem;
56
+ --n-text-2xl: 1.5rem;
57
+ --n-text-3xl: 2rem;
58
+
59
+ --n-weight-normal: 400;
60
+ --n-weight-medium: 500;
61
+ --n-weight-semibold: 600;
62
+ --n-weight-bold: 700;
63
+ --n-weight-extrabold: 800;
64
+
65
+ --n-leading-tight: 1.25;
66
+ --n-leading-normal: 1.5;
67
+ --n-leading-relaxed: 1.75;
68
+
69
+ --n-tracking-tight: -0.025em;
70
+ --n-tracking-normal: 0;
71
+ --n-tracking-wide: 0.05em;
72
+
73
+ /* ─── Spacing (4px base) ─── */
74
+ --n-space-1: 0.25rem;
75
+ --n-space-2: 0.5rem;
76
+ --n-space-3: 0.75rem;
77
+ --n-space-4: 1rem;
78
+ --n-space-5: 1.25rem;
79
+ --n-space-6: 1.5rem;
80
+ --n-space-8: 2rem;
81
+ --n-space-10: 2.5rem;
82
+ --n-space-12: 3rem;
83
+ --n-space-16: 4rem;
84
+
85
+ /* ─── Border Radius ─── */
86
+ --n-radius-sm: 6px;
87
+ --n-radius-md: 10px;
88
+ --n-radius-lg: 14px;
89
+ --n-radius-xl: 20px;
90
+ --n-radius-2xl: 28px;
91
+ --n-radius-full: 9999px;
92
+
93
+ /* ─── Shadows ─── */
94
+ --n-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
95
+ --n-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.2);
96
+ --n-shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
97
+ --n-shadow-xl: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
98
+ --n-shadow-glow-primary: 0 4px 15px -3px rgba(37, 99, 235, 0.3);
99
+ --n-shadow-glow-success: 0 4px 15px -3px rgba(16, 185, 129, 0.3);
100
+ --n-shadow-glow-warning: 0 4px 15px -3px rgba(245, 158, 11, 0.3);
101
+ --n-shadow-glow-info: 0 4px 15px -3px rgba(6, 182, 212, 0.3);
102
+ --n-shadow-glow-danger: 0 4px 15px -3px rgba(220, 38, 38, 0.3);
103
+
104
+ /* ─── Transitions ─── */
105
+ --n-transition-fast: 0.15s ease;
106
+ --n-transition-normal: 0.25s cubic-bezier(0.4, 0, 0.2, 1);
107
+ --n-transition-slow: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
108
+ --n-transition-spring: 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
109
+
110
+ /* ─── Z-Index Scale ─── */
111
+ --n-z-dropdown: 100;
112
+ --n-z-sticky: 200;
113
+ --n-z-overlay: 500;
114
+ --n-z-modal: 2000;
115
+ --n-z-toast: 3000;
116
+ --n-z-tooltip: 1000;
117
+ }
118
+
119
+ /* ─── Light Theme ─── */
120
+ [data-theme="light"] {
121
+ --n-color-primary: #2563eb;
122
+ --n-color-primary-hover: #1d4ed8;
123
+ --n-color-primary-active: #1e40af;
124
+ --n-color-primary-light: rgba(37, 99, 235, 0.08);
125
+ --n-color-primary-glow: rgba(37, 99, 235, 0.2);
126
+
127
+ --n-color-success: #059669;
128
+ --n-color-success-light: rgba(5, 150, 105, 0.08);
129
+
130
+ --n-color-warning: #d97706;
131
+ --n-color-warning-light: rgba(217, 119, 6, 0.08);
132
+
133
+ --n-color-danger: #dc2626;
134
+ --n-color-danger-light: rgba(220, 38, 38, 0.08);
135
+
136
+ --n-color-info: #0891b2;
137
+ --n-color-info-light: rgba(8, 145, 178, 0.08);
138
+
139
+ --n-color-surface: #ffffff;
140
+ --n-color-surface-alt: #f8fafc;
141
+ --n-color-surface-hover: #f1f5f9;
142
+ --n-color-surface-elevated: #ffffff;
143
+
144
+ --n-color-bg: #f8fafc;
145
+ --n-color-bg-alt: #f1f5f9;
146
+
147
+ --n-color-text: #0f172a;
148
+ --n-color-text-secondary: #475569;
149
+ --n-color-text-muted: #94a3b8;
150
+ --n-color-text-inverse: #f8fafc;
151
+
152
+ --n-color-border: rgba(0, 0, 0, 0.08);
153
+ --n-color-border-hover: rgba(0, 0, 0, 0.15);
154
+ --n-color-border-active: rgba(0, 0, 0, 0.25);
155
+
156
+ --n-color-overlay: rgba(15, 23, 42, 0.5);
157
+ --n-color-glass: rgba(255, 255, 255, 0.6);
158
+ --n-color-glass-border: rgba(0, 0, 0, 0.06);
159
+ --n-color-glass-hover: rgba(255, 255, 255, 0.8);
160
+
161
+ --n-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
162
+ --n-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.06);
163
+ --n-shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.08);
164
+ --n-shadow-xl: 0 25px 50px -12px rgba(0, 0, 0, 0.12);
165
+ --n-shadow-glow-primary: 0 4px 15px -3px rgba(37, 99, 235, 0.2);
166
+ --n-shadow-glow-success: 0 4px 15px -3px rgba(5, 150, 105, 0.2);
167
+ --n-shadow-glow-warning: 0 4px 15px -3px rgba(217, 119, 6, 0.2);
168
+ --n-shadow-glow-info: 0 4px 15px -3px rgba(8, 145, 178, 0.2);
169
+ --n-shadow-glow-danger: 0 4px 15px -3px rgba(220, 38, 38, 0.2);
170
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexa-ui-kit",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Premium component library for Nexa Framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,6 +11,10 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js",
13
13
  "default": "./dist/index.js"
14
+ },
15
+ "./styles/tokens.css": {
16
+ "import": "./dist/styles/tokens.css",
17
+ "default": "./dist/styles/tokens.css"
14
18
  }
15
19
  },
16
20
  "files": [
@@ -18,15 +22,15 @@
18
22
  "src"
19
23
  ],
20
24
  "dependencies": {
21
- "nexa-framework": "0.7.1",
22
- "nexa-mobile": "0.7.1"
25
+ "nexa-framework": "0.7.3",
26
+ "nexa-mobile": "0.7.3"
23
27
  },
24
28
  "devDependencies": {
25
29
  "cpx": "^1.5.0",
26
- "nexa-compiler": "0.7.1"
30
+ "nexa-compiler": "0.7.3"
27
31
  },
28
32
  "scripts": {
29
- "build": "tsc && node scripts/compile-nexa.js && node scripts/patch-imports.js && cpx \"src/**/*.nexa\" dist",
33
+ "build": "tsc && node scripts/compile-nexa.js && node scripts/patch-imports.js && cpx \"src/**/*.nexa\" dist && cpx \"src/styles/*.css\" dist/styles",
30
34
  "dev": "tsc --watch"
31
35
  }
32
36
  }
@@ -16,6 +16,8 @@ let modalEl = null
16
16
  let previousFocus = null
17
17
  const bodyOverflow = signal('')
18
18
 
19
+ const setModalRef = (el) => { modalEl = el }
20
+
19
21
  const sizeMap = { sm: '400px', md: '500px', lg: '640px', xl: '800px', full: '96%' }
20
22
 
21
23
  effect(() => {
@@ -90,7 +92,7 @@ onUnmounted(() => {
90
92
  @click="handleOverlayClick"
91
93
  ></div>
92
94
  <div
93
- ref="modalEl"
95
+ :ref="setModalRef"
94
96
  class="n-modal-container"
95
97
  :class="{ 'is-active': show }"
96
98
  :style="{ maxWidth: sizeMap[size] || size }"
@@ -1,16 +1,18 @@
1
1
  <script setup>
2
2
  const props = defineProps({
3
- variant: { type: String, default: 'text' }, // text, circle, card
3
+ variant: { type: String, default: 'text' },
4
4
  lines: { type: Number, default: 3 },
5
5
  width: { type: String, default: '100%' },
6
6
  height: { type: String, default: '' }
7
7
  })
8
+
9
+ const lineArray = Array.from({ length: props.lines || 3 }, (_, i) => i + 1)
8
10
  </script>
9
11
 
10
12
  <template>
11
13
  <div class="n-skeleton" :class="`is-${variant}`" :style="{ width, height }">
12
14
  <div v-if="variant === 'text'" class="n-skeleton-lines">
13
- <div v-for="i in lines" :key="i" class="n-skeleton-line" :style="{ width: i === lines ? '60%' : '100%' }"></div>
15
+ <div v-for="n in lineArray" :key="n" class="n-skeleton-line" :style="{ width: n === lineArray.length ? '60%' : '100%' }"></div>
14
16
  </div>
15
17
  <div v-if="variant === 'circle'" class="n-skeleton-circle"></div>
16
18
  <div v-if="variant === 'card'" class="n-skeleton-card">
@@ -9,14 +9,23 @@ export interface Toast {
9
9
  duration?: number
10
10
  }
11
11
 
12
- const toasts = signal<Toast[]>([])
13
- let nextId = 1
12
+ const g = globalThis as any
13
+ const GLOBAL_KEY = '__NEXA_TOAST_SERVICE__'
14
+
15
+ if (!g[GLOBAL_KEY]) {
16
+ g[GLOBAL_KEY] = {
17
+ toasts: signal<Toast[]>([]),
18
+ nextId: 1
19
+ }
20
+ }
21
+
22
+ const state = g[GLOBAL_KEY] as { toasts: ReturnType<typeof signal<Toast[]>>, nextId: number }
14
23
 
15
24
  export const useToast = () => {
16
25
  const add = (message: string, type: ToastType = 'info', duration: number = 3000) => {
17
- const id = nextId++
26
+ const id = state.nextId++
18
27
  const toast: Toast = { id, message, type, duration }
19
- toasts.value = [...toasts.value, toast]
28
+ state.toasts.value = [...state.toasts.value, toast]
20
29
 
21
30
  if (duration > 0) {
22
31
  setTimeout(() => remove(id), duration)
@@ -26,11 +35,11 @@ export const useToast = () => {
26
35
  }
27
36
 
28
37
  const remove = (id: number) => {
29
- toasts.value = toasts.value.filter((t: any) => t.id !== id)
38
+ state.toasts.value = state.toasts.value.filter((t: any) => t.id !== id)
30
39
  }
31
40
 
32
41
  return {
33
- toasts,
42
+ toasts: state.toasts,
34
43
  add,
35
44
  remove,
36
45
  success: (msg: string, dur?: number) => add(msg, 'success', dur),