poe-svelte-ui-lib 1.0.4 → 1.0.6

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.
@@ -17,16 +17,30 @@
17
17
  transition:slide={{ duration: 250 }}
18
18
  >
19
19
  <button
20
- class="flex w-full cursor-pointer items-center justify-between transition-shadow duration-250 sm:p-4 sm:px-6
20
+ class="flex p-4 w-full cursor-pointer items-center justify-between transition-shadow duration-250
21
21
  {props.type === 'sub' ? 'border-b border-[var(--border-color)]' : ''}"
22
22
  onclick={toggle}
23
23
  >
24
- <span class="toggle m-0 cursor-pointer text-lg font-semibold {props.label?.class}">
25
- {props.label?.name}
26
- </span>
24
+ <div class="flex items-center w-full">
25
+ <span class={`flex items-center justify-center w-8 h-8 shrink-0 overflow-visible [&_svg]:w-full [&_svg]:h-full [&_svg]:max-w-full [&_svg]:max-h-full`}>
26
+ {#if props.icon?.svg}
27
+ {@html props.icon.svg}
28
+ {:else if props.icon?.component}
29
+ {@const IconComponent = props.icon?.component}
30
+ <IconComponent />
31
+ {/if}
32
+ </span>
33
+ <h4
34
+ class="{props.label?.class}
35
+ {props.label?.align === 'center' ? 'text-center flex-1' : props.label?.align === 'right' ? 'text-right flex-1 mr-2' : 'text-left flex-1 ml-2'}"
36
+ >
37
+ {props.label?.name}
38
+ </h4>
39
+ </div>
40
+
27
41
  <svg
28
42
  xmlns="http://www.w3.org/2000/svg"
29
- class="arrow h-[1.1rem] w-[1.1rem] transition-transform duration-250"
43
+ class="h-[1.1rem] w-[1.1rem] transition-transform duration-250"
30
44
  style="transform: rotate({isOpen ? 180 : 0}deg)"
31
45
  viewBox="0 0 24 24"
32
46
  >
@@ -35,7 +49,7 @@
35
49
  stroke="currentColor"
36
50
  stroke-linecap="round"
37
51
  stroke-linejoin="round"
38
- stroke-width="1.5"
52
+ stroke-width="2"
39
53
  d="M18 12.5s-4.419 6-6 6s-6-6-6-6m12-7s-4.419 6-6 6s-6-6-6-6"
40
54
  color="currentColor"
41
55
  />
@@ -44,8 +58,9 @@
44
58
 
45
59
  {#if isOpen}
46
60
  <div
47
- class="flex w-full flex-wrap items-start justify-around p-4 sm:p-3 {props.type === 'sub' ? '' : 'border-t border-[var(--border-color)]'}"
61
+ class="flex w-full flex-wrap items-start justify-around p-2 {props.type === 'sub' ? '' : 'border-t border-[var(--border-color)]'}"
48
62
  transition:slide={{ duration: 250 }}
63
+ style={props.image ? `background-image: url('${props.image}'); background-size: cover;` : ''}
49
64
  >
50
65
  {@render props.children?.()}
51
66
  </div>
@@ -34,7 +34,6 @@
34
34
  { id: 'RefreshOption-1000', name: '1000', value: 1000, class: '' },
35
35
  { id: 'RefreshOption-5000', name: '5000', value: 5000, class: '' },
36
36
  ]
37
- // const REFRESH_OPTIONS = [10, 25, 50, 100, 250, 500, 1000, 5000]
38
37
  const SCALE_OPTIONS: ISelectOption[] = [
39
38
  { id: 'ScaleOption-50', name: '50', value: 50, class: '' },
40
39
  { id: 'ScaleOption-100', name: '100', value: 100, class: '' },
@@ -42,7 +41,6 @@
42
41
  { id: 'ScaleOption-1000', name: '1000', value: 1000, class: '' },
43
42
  { id: 'ScaleOption-2000', name: '2000', value: 2000, class: '' },
44
43
  ]
45
- // const SCALE_OPTIONS = [50, 100, 500, 1000, 2000]
46
44
  let selectedRefreshRate = $state(0)
47
45
  let selectedScale = $state(100)
48
46
  const maxDataPoints = $derived(selectedRefreshRate == 0 ? 20 : 100)
@@ -246,7 +244,7 @@
246
244
  <Select
247
245
  label={{ name: 'Scale' }}
248
246
  options={SCALE_OPTIONS}
249
- value={REFRESH_OPTIONS.find((o) => o.value == selectedScale)}
247
+ value={SCALE_OPTIONS.find((o) => o.value == selectedScale)}
250
248
  onUpdate={(value) => (selectedScale = value.value as number)}
251
249
  />
252
250
 
@@ -173,7 +173,7 @@
173
173
  class="absolute top-1/2 right-10 -translate-y-1/2 transform rounded-md bg-[var(--green-color)] px-2 py-1 text-sm shadow-lg"
174
174
  transition:fly={{ x: 10, duration: 200 }}
175
175
  >
176
-
176
+
177
177
  </div>
178
178
  {/if}
179
179
  {/if}
@@ -18,6 +18,7 @@
18
18
  type = 'select',
19
19
  value = $bindable(),
20
20
  options = [],
21
+ placeholder= '---',
21
22
  onUpdate,
22
23
  }: ISelectProps<T> = $props()
23
24
 
@@ -101,7 +102,7 @@
101
102
  aria-expanded={isDropdownOpen}
102
103
  {disabled}
103
104
  >
104
- {value?.name || ''}
105
+ {value?.name || placeholder}
105
106
  </button>
106
107
 
107
108
  {#if isDropdownOpen}
@@ -1,6 +1,9 @@
1
1
  <!-- $lib/ElementsUI/Slider.svelte -->
2
2
  <script lang="ts">
3
3
  import type { ISliderProps } from '../types'
4
+ import IconGripVerticalLeft from '../libIcons/IconGripVerticalLeft.svelte'
5
+ import IconGripVerticalRight from '../libIcons/IconGripVerticalRight.svelte'
6
+ import IconGripVerticalDual from '../libIcons/IconGripVerticalDual.svelte'
4
7
 
5
8
  let {
6
9
  id = { name: '', value: crypto.randomUUID() },
@@ -94,17 +97,17 @@
94
97
  {/if}
95
98
 
96
99
  <!-- Слайдер -->
97
- <div class="relative flex h-2 w-full justify-center {disabled ? 'opacity-50' : ''}" id={id.value}>
100
+ <div class="relative flex h-8 rounded-full w-full justify-center {disabled ? 'opacity-50 cursor-not-allowed' : ''}" id={id.value}>
98
101
  {#if isRange}
99
102
  <!-- Трек и активная зона -->
100
103
  <div
101
- class={`absolute h-full w-full rounded bg-gray-400 ${disabled ? '' : 'cursor-pointer'}`}
104
+ class={`absolute h-full w-full rounded-full bg-[var(--gray-color)] ${disabled ? '' : 'cursor-pointer'}`}
102
105
  role="button"
103
106
  tabindex={null}
104
107
  onkeydown={null}
105
108
  onclick={disabled ? undefined : handleTrackClick}
106
109
  >
107
- <div class="absolute h-full rounded" style={`left: ${lowerPosition}%; right: ${100 - upperPosition}%; background-color: var(--bg-color)`}></div>
110
+ <div class="absolute h-full rounded-full bg-[var(--bg-color)]" style={`left: ${lowerPosition}%; right: ${100 - upperPosition}%;`}></div>
108
111
  </div>
109
112
 
110
113
  <!-- Ползунки -->
@@ -125,6 +128,12 @@
125
128
  {disabled}
126
129
  class={`absolute h-full w-full appearance-none bg-transparent ${activeThumb === 'lower' ? 'z-30' : 'z-20'}`}
127
130
  />
131
+ <div
132
+ class="absolute z-40 pointer-events-none rounded-full bg-[var(--field-color)]"
133
+ style={`left: calc(${lowerPosition}% + 0rem); top: 50%; transform: translateY(-50%)`}
134
+ >
135
+ <IconGripVerticalLeft />
136
+ </div>
128
137
 
129
138
  <input
130
139
  type="range"
@@ -143,16 +152,25 @@
143
152
  {disabled}
144
153
  class={`absolute h-full w-full appearance-none bg-transparent ${activeThumb === 'upper' ? 'z-30' : 'z-20'}`}
145
154
  />
155
+ <div
156
+ class="absolute z-40 pointer-events-none rounded-full bg-[var(--field-color)]"
157
+ style={`left: calc(${upperPosition}% - 2rem); top: 50%; transform: translateY(-50%)`}
158
+ >
159
+ <IconGripVerticalRight />
160
+ </div>
146
161
  {:else}
147
162
  <!-- Одиночный слайдер -->
148
163
  <div
149
- class={`absolute h-full w-full rounded bg-gray-400 ${disabled ? '' : 'cursor-pointer'}`}
164
+ class={`absolute h-full w-full rounded-full bg-[var(--gray-color)] ${disabled ? '' : 'cursor-pointer'}`}
150
165
  role="button"
151
166
  tabindex={null}
152
167
  onkeydown={null}
153
168
  onclick={disabled ? undefined : handleTrackClick}
154
169
  >
155
- <div class="absolute h-full rounded" style={`width: ${singlePosition}%; background-color: var(--bg-color)`}></div>
170
+ <div
171
+ class="absolute h-full {singlePosition === 100 ? 'rounded-full z-10' : 'rounded-l-full z-10'}"
172
+ style={`width: ${singlePosition}%; background-color: var(--bg-color)`}
173
+ ></div>
156
174
  </div>
157
175
 
158
176
  <input
@@ -168,8 +186,14 @@
168
186
  }}
169
187
  onmouseup={disabled ? undefined : () => onUpdate(singleValue)}
170
188
  {disabled}
171
- class="absolute z-30 h-full w-full appearance-none bg-transparent"
189
+ class="absolute z-20 h-full w-full appearance-none bg-transparent"
172
190
  />
191
+ <div
192
+ class="absolute z-30 pointer-events-none rounded-full bg-[var(--field-color)]"
193
+ style={`left: clamp(1rem, ${singlePosition}%, calc(100% - 1rem)); top: 50%; transform: translate(-50%, -50%)`}
194
+ >
195
+ <IconGripVerticalDual />
196
+ </div>
173
197
  {/if}
174
198
  </div>
175
199
 
@@ -220,41 +244,56 @@
220
244
  margin: 0;
221
245
  padding: 0;
222
246
  pointer-events: none;
247
+ outline: none;
223
248
  }
224
249
 
225
- input[type='range']:disabled::-webkit-slider-thumb {
226
- cursor: auto;
227
- }
228
-
250
+ /* Webkit thumb */
229
251
  input[type='range']::-webkit-slider-thumb {
230
252
  -webkit-appearance: none;
231
253
  appearance: none;
232
- width: 1rem;
233
- height: 1rem;
254
+ width: 2rem;
255
+ height: 2rem;
234
256
  border-radius: 50%;
235
- background: var(--border-color);
257
+ background: transparent;
236
258
  cursor: pointer;
237
259
  pointer-events: auto;
238
- transition: all 0.2s ease;
239
- }
240
-
241
- input[type='range']:disabled::-webkit-slider-thumb {
242
- background: var(--gray-color);
260
+ border: none;
243
261
  }
244
262
 
263
+ /* Firefox thumb */
245
264
  input[type='range']::-moz-range-thumb {
246
- width: 1rem;
247
- height: 1rem;
265
+ width: 2rem;
266
+ height: 2rem;
248
267
  border-radius: 50%;
249
- background: var(--border-color);
268
+ background: transparent;
250
269
  cursor: pointer;
251
270
  pointer-events: auto;
252
271
  border: none;
253
- transition: all 0.2s ease;
272
+ }
273
+
274
+ /* Webkit track */
275
+ input[type='range']::-webkit-slider-runnable-track {
276
+ width: 100%;
277
+ height: 100%;
278
+ background: transparent;
279
+ border-radius: 0;
280
+ border: none;
281
+ }
282
+
283
+ /* Firefox track */
284
+ input[type='range']::-moz-range-track {
285
+ width: 100%;
286
+ height: 100%;
287
+ background: transparent;
288
+ border-radius: 0;
289
+ border: none;
290
+ }
291
+
292
+ input[type='range']:disabled::-webkit-slider-thumb {
293
+ cursor: not-allowed;
254
294
  }
255
295
 
256
296
  input[type='range']:disabled::-moz-range-thumb {
257
- background: var(--gray-color);
258
297
  cursor: not-allowed;
259
298
  }
260
299
  </style>
@@ -15,7 +15,7 @@
15
15
  const options = [1, 2]
16
16
  let checked = $derived(value === options[1])
17
17
 
18
- let knobTransform = $derived(checked ? `translateX(calc(${height} * 0.9))` : 'translateX(0)')
18
+ let knobTransform = $derived(checked ? `translateX(calc(${height}))` : 'translateX(0)')
19
19
 
20
20
  $effect(() => {
21
21
  if (value === undefined || value === null) value = options[0]
@@ -66,14 +66,15 @@
66
66
  onchange={handleToggle}
67
67
  />
68
68
  <span
69
- class="relative flex items-center rounded-full transition-all duration-250 {checked ? '!bg-[var(--bg-color)]' : '!bg-[var(--gray-color)]'} {disabled
70
- ? ''
71
- : 'cursor-pointer'}"
69
+ class="relative flex items-center rounded-full transition-all duration-250
70
+ {checked ? '!bg-[var(--bg-color)]' : '!bg-[var(--gray-color)]'}
71
+ {disabled ? '' : 'cursor-pointer'}"
72
72
  style="width: {`calc(${height} * 2)`}; height: {height};"
73
73
  >
74
74
  <span
75
- class="absolute rounded-full bg-[var(--back-color)] transition-all duration-250 {disabled ? 'opacity-60' : 'cursor-pointer'}"
76
- style="width: {`calc(${height} * 0.8)`}; height: {`calc(${height} * 0.8)`}; margin: 0 {`calc(${height} * 0.1)`}; transform: {knobTransform};"
75
+ class="absolute rounded-full bg-[var(--back-color)] transition-all duration-250
76
+ {disabled ? 'opacity-60' : 'cursor-pointer'}"
77
+ style="width: {`calc(${height} * 0.75)`}; height: {`calc(${height} * 0.75)`}; margin: 0 {`calc(${height} * 0.1)`}; transform: {knobTransform};"
77
78
  ></span>
78
79
  </span>
79
80
  </label>
@@ -8,12 +8,12 @@
8
8
  id = { value: crypto.randomUUID(), name: '' },
9
9
  wrapperClass = 'bg-blue',
10
10
  label = { name: '', class: '' },
11
- tableBody = [],
12
- tableHeader = [],
11
+ body = [],
12
+ header = [],
13
+ footer = '',
13
14
  cursor = null,
14
15
  loader,
15
16
  getData = () => {},
16
- info = '',
17
17
  modalData = $bindable({ isOpen: false, rawData: '', formattedData: '' }),
18
18
  onClick,
19
19
  }: ITableProps<any> = $props()
@@ -36,7 +36,7 @@
36
36
  sortState.direction = 'asc'
37
37
  }
38
38
 
39
- tableBody = [...tableBody].sort((a, b) => {
39
+ body = [...body].sort((a, b) => {
40
40
  const aValue = a[key]
41
41
  const bValue = b[key]
42
42
  if (typeof aValue === 'number' && typeof bValue === 'number') {
@@ -126,8 +126,8 @@
126
126
 
127
127
  <div class="flex h-full flex-col overflow-hidden rounded-xl border-[var(--border-color)]">
128
128
  <!-- Table Header -->
129
- <div class="grid font-semibold" style={`grid-template-columns: ${tableHeader.map((c) => c.width || 'minmax(0, 1fr)').join(' ')};`}>
130
- {#each tableHeader as column (column)}
129
+ <div class="grid font-semibold" style={`grid-template-columns: ${header.map((c) => c.width || 'minmax(0, 1fr)').join(' ')};`}>
130
+ {#each header as column (column)}
131
131
  <div class="justify-center bg-[var(--bg-color)] p-2 text-center">
132
132
  <div class="flex items-center justify-start gap-2">
133
133
  <span>{column.label}</span>
@@ -146,9 +146,9 @@
146
146
 
147
147
  <!-- Table Body с прокруткой -->
148
148
  <div class="flex-1 overflow-y-auto bg-[var(--conteiner-color)]/50" bind:this={container} onscroll={handleScroll}>
149
- <div class="grid min-w-0" style={`grid-template-columns: ${tableHeader.map((c) => c.width || 'minmax(0, 1fr)').join(' ')};`}>
150
- {#each tableBody as row, index (row)}
151
- {#each tableHeader as column (column)}
149
+ <div class="grid min-w-0" style={`grid-template-columns: ${header.map((c) => c.width || 'minmax(0, 1fr)').join(' ')};`}>
150
+ {#each body as row, index (row)}
151
+ {#each header as column (column)}
152
152
  <div
153
153
  class="relative flex w-full min-w-0 items-center px-2 py-1 break-words
154
154
  {index % 2 ? '!bg-[var(--back-color)]/40' : ''}
@@ -218,7 +218,7 @@
218
218
 
219
219
  {#if column.overflow?.copy}
220
220
  <button
221
- class="right-2 flex cursor-pointer border-none bg-transparent"
221
+ class="m-2 flex cursor-pointer border-none bg-transparent text-2xl"
222
222
  onclick={(e) => {
223
223
  e.preventDefault()
224
224
  navigator.clipboard.writeText(row[column.key])
@@ -227,24 +227,19 @@
227
227
  }}
228
228
  aria-label="Копировать текст"
229
229
  >
230
- <svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" viewBox="0 0 24 24">
231
- <g fill="none" stroke="currentColor" stroke-width="1.5">
232
- <path
233
- d="M6 11c0-2.828 0-4.243.879-5.121C7.757 5 9.172 5 12 5h3c2.828 0 4.243 0 5.121.879C21 6.757 21 8.172 21 11v5c0 2.828 0 4.243-.879 5.121C19.243 22 17.828 22 15 22h-3c-2.828 0-4.243 0-5.121-.879C6 20.243 6 18.828 6 16z"
234
- />
235
- <path d="M6 19a3 3 0 0 1-3-3v-6c0-3.771 0-5.657 1.172-6.828S7.229 2 11 2h4a3 3 0 0 1 3 3" />
236
- </g>
237
- </svg>
230
+ {#if copiedCell.y === index && copiedCell.x === column.key}
231
+
232
+ {:else}
233
+ <svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" viewBox="0 0 24 24">
234
+ <g fill="none" stroke="currentColor" stroke-width="1.5">
235
+ <path
236
+ d="M6 11c0-2.828 0-4.243.879-5.121C7.757 5 9.172 5 12 5h3c2.828 0 4.243 0 5.121.879C21 6.757 21 8.172 21 11v5c0 2.828 0 4.243-.879 5.121C19.243 22 17.828 22 15 22h-3c-2.828 0-4.243 0-5.121-.879C6 20.243 6 18.828 6 16z"
237
+ />
238
+ <path d="M6 19a3 3 0 0 1-3-3v-6c0-3.771 0-5.657 1.172-6.828S7.229 2 11 2h4a3 3 0 0 1 3 3" />
239
+ </g>
240
+ </svg>
241
+ {/if}
238
242
  </button>
239
-
240
- {#if copiedCell.y === index && copiedCell.x === column.key}
241
- <div
242
- class="absolute top-1/2 right-10 -translate-y-1/2 transform rounded-md bg-[var(--green-color)] px-2 py-1 text-sm shadow-lg"
243
- transition:fly={{ x: 10, duration: 200 }}
244
- >
245
-
246
- </div>
247
- {/if}
248
243
  {/if}
249
244
  {/if}
250
245
  </div>
@@ -266,9 +261,9 @@
266
261
  {/if}
267
262
 
268
263
  <!-- Нижнее поле для сводной информации -->
269
- {#if info != ''}
264
+ {#if footer != ''}
270
265
  <div class="flex h-8 items-center justify-center bg-[var(--bg-color)]">
271
- <h5>{info}</h5>
266
+ <h5>{footer}</h5>
272
267
  </div>
273
268
  {/if}
274
269
  </div>
@@ -1,22 +1,20 @@
1
1
  <script lang="ts">
2
2
  import type { ITextFieldProps } from '../types'
3
3
 
4
- let {
5
- id = { value: crypto.randomUUID(), name: '' },
6
- wrapperClass = '',
7
- label = { name: '', class: '' },
8
- type = 'small',
9
- bold = false,
10
- italic = false,
11
- }: ITextFieldProps = $props()
4
+ let { id = crypto.randomUUID(), wrapperClass = '', label = { name: '', bold: false, italic: false, color: '' }, type = 'small' }: ITextFieldProps = $props()
12
5
 
13
6
  const textSize = {
7
+ xsmall: 'text-sm',
14
8
  small: 'text-base',
15
- medium: 'text-xl',
9
+ medium: 'text-lg',
10
+ large: 'text-xl',
16
11
  xlarge: 'text-2xl',
17
- }
12
+ xxlarge: 'text-3xl',
13
+ huge: 'text-4xl',
14
+ massive: 'text-5xl',
15
+ } as const
18
16
  </script>
19
17
 
20
- <div id={id.value} class="relative flex w-full flex-col items-center {wrapperClass}">
21
- <p class="w-full text-center {label.class} {textSize[type]} {bold ? 'font-bold' : ''} {italic ? 'italic' : ''}">{label.name}</p>
18
+ <div {id} class="relative flex w-full flex-col items-center {wrapperClass}">
19
+ <p class="w-full text-center {label.color} {textSize[type]} {label.bold ? 'font-bold' : ''} {label.italic ? 'italic' : ''}">{label.name}</p>
22
20
  </div>
@@ -0,0 +1,92 @@
1
+ <!-- $lib/ElementsUI/GridAccordionProps.svelte -->
2
+ <script lang="ts">
3
+ import { t } from '../locales/i18n'
4
+ import type { ITextFieldProps, UIComponent } from '../types'
5
+ import * as UI from '../index'
6
+ import { optionsStore } from '../options'
7
+
8
+ const { component, onPropertyChange } = $props<{
9
+ component: UIComponent & { properties: Partial<ITextFieldProps> }
10
+ onPropertyChange: (value: string | object) => void
11
+ }>()
12
+
13
+ let currentType = $derived($optionsStore.TEXTFIELD_SIZE_OPTIONS.find((t) => t.value === component.properties.type))
14
+
15
+ const initialAlign = $derived(
16
+ $optionsStore.ALIGN_OPTIONS.find((a) =>
17
+ (a.value as string).includes(component.properties.label?.class?.split(' ').find((cls: string) => cls.startsWith('text-'))),
18
+ ),
19
+ )
20
+
21
+ const handleLabelAlign = (align: string) => {
22
+ let labelClass = component.properties.label.class || ''
23
+ labelClass = labelClass
24
+ .split(' ')
25
+ .filter((cls: string) => !cls.startsWith('text-'))
26
+ .join(' ')
27
+ if (align) {
28
+ labelClass += ` ${align}`
29
+ }
30
+ updateProperty('label.class', labelClass)
31
+ }
32
+
33
+ /* Обновление свойства */
34
+ const updateProperty = (path: string, value: string | object | boolean) => {
35
+ const newProperties = JSON.parse(JSON.stringify(component.properties))
36
+ const parts = path.split('.')
37
+ let obj = newProperties
38
+
39
+ for (let i = 0; i < parts.length - 1; i++) {
40
+ const part = parts[i]
41
+ if (!obj[part]) obj[part] = {}
42
+ obj = obj[part]
43
+ }
44
+
45
+ obj[parts[parts.length - 1]] = value
46
+ onPropertyChange(newProperties)
47
+ }
48
+ </script>
49
+
50
+ {#if component && component.properties}
51
+ <div class="relative flex flex-row items-start justify-center">
52
+ <div class="flex w-1/3 flex-col px-2">
53
+ <UI.Input
54
+ label={{ name: $t('constructor.props.label') }}
55
+ value={component.properties.label.name}
56
+ onUpdate={(value) => updateProperty('label.name', value as string)}
57
+ type="text"
58
+ />
59
+ <UI.Select
60
+ label={{ name: $t('constructor.props.type') }}
61
+ type="buttons"
62
+ value={currentType}
63
+ options={$optionsStore.TEXTFIELD_SIZE_OPTIONS}
64
+ onUpdate={(item) => updateProperty('type', item.value as string)}
65
+ />
66
+ </div>
67
+ <div class="flex w-1/3 flex-col px-2">
68
+ <UI.Select
69
+ wrapperClass="w-full"
70
+ label={{ name: $t('constructor.props.align') }}
71
+ type="buttons"
72
+ value={initialAlign}
73
+ options={$optionsStore.ALIGN_OPTIONS}
74
+ onUpdate={(option) => handleLabelAlign(option.value as string)}
75
+ />
76
+ </div>
77
+ <div class="flex w-1/3 flex-col px-2">
78
+ <UI.Switch
79
+ wrapperClass="w-full bg-blue"
80
+ label={{ name: $t('constructor.props.bold') }}
81
+ value={component.properties.bold ? 2 : 1}
82
+ onChange={(value) => updateProperty('bold', value === 2)}
83
+ />
84
+ <UI.Switch
85
+ wrapperClass="w-full bg-blue"
86
+ label={{ name: $t('constructor.props.italic') }}
87
+ value={component.properties.italic ? 2 : 1}
88
+ onChange={(value) => updateProperty('italic', value === 2)}
89
+ />
90
+ </div>
91
+ </div>
92
+ {/if}
@@ -0,0 +1,10 @@
1
+ import type { ITextFieldProps, UIComponent } from '../types';
2
+ type $$ComponentProps = {
3
+ component: UIComponent & {
4
+ properties: Partial<ITextFieldProps>;
5
+ };
6
+ onPropertyChange: (value: string | object) => void;
7
+ };
8
+ declare const TextFieldProps: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type TextFieldProps = ReturnType<typeof TextFieldProps>;
10
+ export default TextFieldProps;
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export { default as Slider } from './Slider/Slider.svelte';
10
10
  export { default as Switch } from './Switch/Switch.svelte';
11
11
  export { default as Table } from './Table/Table.svelte';
12
12
  export { default as TextField } from './TextField/TextField.svelte';
13
+ export { default as TextFieldProps } from './TextField/TextFieldProps.svelte';
13
14
  export { default as Loader } from './Loader.svelte';
14
15
  export { default as MessageModal } from './MessageModal.svelte';
15
16
  export { type UIComponent, type Position, type IUIComponentHandler, type IButtonProps, type IAccordionProps, type IInputProps, type ISelectProps, type ISelectOption, type ISwitchProps, type IColorPickerProps, type ISliderProps, type ITextFieldProps, type IProgressBarProps, type IGraphProps, type IGraphDataObject, type ITableHeader, type ITableProps, } from './types';
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ export { default as Slider } from './Slider/Slider.svelte';
11
11
  export { default as Switch } from './Switch/Switch.svelte';
12
12
  export { default as Table } from './Table/Table.svelte';
13
13
  export { default as TextField } from './TextField/TextField.svelte';
14
+ export { default as TextFieldProps } from './TextField/TextFieldProps.svelte';
14
15
  export { default as Loader } from './Loader.svelte';
15
16
  export { default as MessageModal } from './MessageModal.svelte';
16
17
  export {} from './types';
@@ -0,0 +1,12 @@
1
+ <!-- appIcons/IconGripVerticalDual.svelte -->
2
+ <script lang="ts"></script>
3
+
4
+ <svg xmlns="http://www.w3.org/2000/svg" width="2rem" height="2rem" viewBox="0 0 24 24">
5
+ <g stroke="currentColor" stroke-linecap="round" stroke-width="1.5" fill="none">
6
+ <line x1="4" y1="11" x2="4" y2="13" />
7
+ <line x1="8" y1="9" x2="8" y2="15" />
8
+ <line x1="12" y1="6" x2="12" y2="18" />
9
+ <line x1="16" y1="9" x2="16" y2="15" />
10
+ <line x1="20" y1="11" x2="20" y2="13" />
11
+ </g>
12
+ </svg>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const IconGripVerticalDual: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type IconGripVerticalDual = InstanceType<typeof IconGripVerticalDual>;
18
+ export default IconGripVerticalDual;
@@ -0,0 +1,9 @@
1
+ <script lang="ts"></script>
2
+
3
+ <svg xmlns="http://www.w3.org/2000/svg" width="2rem" height="2rem" viewBox="0 0 24 24">
4
+ <g stroke="currentColor" stroke-linecap="round" stroke-width="1.5" fill="none">
5
+ <line x1="8" y1="11" x2="8" y2="13" />
6
+ <line x1="12" y1="9" x2="12" y2="15" />
7
+ <line x1="16" y1="6" x2="16" y2="18" />
8
+ </g>
9
+ </svg>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const IconGripVerticalLeft: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type IconGripVerticalLeft = InstanceType<typeof IconGripVerticalLeft>;
18
+ export default IconGripVerticalLeft;
@@ -0,0 +1,9 @@
1
+ <script lang="ts"></script>
2
+
3
+ <svg xmlns="http://www.w3.org/2000/svg" width="2rem" height="2rem" viewBox="0 0 24 24">
4
+ <g stroke="currentColor" stroke-linecap="round" stroke-width="1.5" fill="none">
5
+ <line x1="8" y1="6" x2="8" y2="18" />
6
+ <line x1="12" y1="9" x2="12" y2="15" />
7
+ <line x1="16" y1="11" x2="16" y2="13" />
8
+ </g>
9
+ </svg>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const IconGripVerticalRight: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type IconGripVerticalRight = InstanceType<typeof IconGripVerticalRight>;
18
+ export default IconGripVerticalRight;
@@ -0,0 +1,9 @@
1
+ import { type Readable } from 'svelte/store';
2
+ export declare const Language: import("svelte/store").Writable<string>;
3
+ export declare function setLanguage(newLang: string): void;
4
+ export declare const LOCALES: {
5
+ id: string;
6
+ name: string;
7
+ value: string;
8
+ }[];
9
+ export declare const t: Readable<(key: string) => string>;
@@ -0,0 +1,33 @@
1
+ import { derived } from 'svelte/store';
2
+ import { writable } from 'svelte/store';
3
+ import translations from './translations';
4
+ /* Язык по умолчанию */
5
+ let initialLanguage = 'ru';
6
+ /* Проверяем, доступен ли localStorage */
7
+ if (typeof window !== 'undefined') {
8
+ initialLanguage = localStorage.getItem('AppLanguage') || navigator.language?.split('-')[0]?.toLowerCase() || 'ru';
9
+ const supported = ['ru', 'en', 'zh'];
10
+ if (!supported.includes(initialLanguage)) {
11
+ initialLanguage = 'ru';
12
+ }
13
+ }
14
+ /* Создаем хранилище с начальным значением языка */
15
+ export const Language = writable(initialLanguage);
16
+ /* Функция для изменения языка */
17
+ export function setLanguage(newLang) {
18
+ if (typeof window !== 'undefined') {
19
+ localStorage.setItem('AppLanguage', newLang);
20
+ }
21
+ Language.set(newLang);
22
+ }
23
+ /* Поддерживаемые языки (код, название языка, флаг) */
24
+ export const LOCALES = [
25
+ { id: 'app-language-ru', name: 'РУС', value: 'ru' },
26
+ { id: 'app-language-en', name: 'ENG', value: 'en' },
27
+ { id: 'app-language-zh', name: '中文', value: 'zh' },
28
+ ];
29
+ /* Функция для перевода для текущего языка */
30
+ function translate(locale, key) {
31
+ return translations[locale]?.[key] || key;
32
+ }
33
+ export const t = derived(Language, ($lang) => (key) => translate($lang, key));
@@ -0,0 +1,7 @@
1
+ interface Translations {
2
+ [language: string]: {
3
+ [key: string]: string;
4
+ };
5
+ }
6
+ declare const translations: Translations;
7
+ export default translations;
@@ -0,0 +1,18 @@
1
+ const translations = {
2
+ ru: {
3
+ 'constructor.props.label': 'Текст надписи',
4
+ 'constructor.props.type': 'Тип',
5
+ 'constructor.props.align': 'Выравнивание',
6
+ 'constructor.props.bold': 'Жирный',
7
+ 'constructor.props.italic': 'Курсив',
8
+ 'constructor.props.type.small': 'Малый',
9
+ 'constructor.props.type.medium': 'Обычный',
10
+ 'constructor.props.type.xlarge': 'Большой',
11
+ 'constructor.props.align.left': 'Слева',
12
+ 'constructor.props.align.center': 'По центру',
13
+ 'constructor.props.align.right': 'Справа',
14
+ },
15
+ en: {},
16
+ zh: {},
17
+ };
18
+ export default translations;
package/dist/options.d.ts CHANGED
@@ -8,47 +8,47 @@ export declare const optionsStore: import("svelte/store").Readable<{
8
8
  SHORT_ARGUMENT_OPTION: {
9
9
  id: string;
10
10
  value: string;
11
- name: any;
11
+ name: string;
12
12
  class: string;
13
13
  }[];
14
14
  FULL_ARGUMENT_OPTION: {
15
15
  id: string;
16
16
  value: string;
17
- name: any;
17
+ name: string;
18
18
  class: string;
19
19
  }[];
20
20
  INPUT_TYPE_OPTIONS: {
21
21
  id: string;
22
22
  value: string;
23
- name: any;
23
+ name: string;
24
24
  }[];
25
25
  SELECT_TYPE_OPTIONS: {
26
26
  id: string;
27
27
  value: string;
28
- name: any;
28
+ name: string;
29
29
  class: string;
30
30
  }[];
31
31
  SELECT_VALUE_TYPE_OPTIONS: ({
32
32
  id: string;
33
33
  value: "text";
34
- name: any;
34
+ name: string;
35
35
  class: string;
36
36
  } | {
37
37
  id: string;
38
38
  value: "number";
39
- name: any;
39
+ name: string;
40
40
  class: string;
41
41
  })[];
42
42
  SLIDER_TYPE_OPTIONS: {
43
43
  id: string;
44
44
  value: string;
45
- name: any;
45
+ name: string;
46
46
  class: string;
47
47
  }[];
48
48
  TEXTFIELD_SIZE_OPTIONS: {
49
49
  id: string;
50
50
  value: string;
51
- name: any;
51
+ name: string;
52
52
  class: string;
53
53
  }[];
54
54
  COLOR_OPTIONS: {
@@ -60,19 +60,19 @@ export declare const optionsStore: import("svelte/store").Readable<{
60
60
  ALIGN_OPTIONS: {
61
61
  id: string;
62
62
  value: string;
63
- name: any;
63
+ name: string;
64
64
  class: string;
65
65
  }[];
66
66
  HEIGHT_OPTIONS: {
67
67
  id: string;
68
68
  value: string;
69
- name: any;
69
+ name: string;
70
70
  class: string;
71
71
  }[];
72
72
  ACCORDION_TYPE_OPTIONS: {
73
73
  id: string;
74
74
  value: string;
75
- name: any;
75
+ name: string;
76
76
  class: string;
77
77
  }[];
78
78
  }>;
package/dist/types.d.ts CHANGED
@@ -49,13 +49,18 @@ export interface IButtonProps {
49
49
  onClick?: () => void;
50
50
  }
51
51
  export interface IAccordionProps {
52
- id?: {
52
+ id: {
53
53
  value?: string;
54
54
  name?: string;
55
55
  };
56
56
  label?: {
57
57
  name?: string;
58
58
  class?: string;
59
+ align?: 'left' | 'center' | 'right';
60
+ };
61
+ icon?: {
62
+ svg?: string;
63
+ component?: ConstructorOfATypedSvelteComponent | null;
59
64
  };
60
65
  isOpen: boolean;
61
66
  componentClass?: string;
@@ -110,6 +115,7 @@ export interface ISelectProps<T = unknown> {
110
115
  type?: 'select' | 'buttons' | 'input';
111
116
  value?: ISelectOption<T> | null;
112
117
  options?: ISelectOption<T>[];
118
+ placeholder?: string;
113
119
  eventHandler?: IUIComponentHandler;
114
120
  onUpdate?: (value: ISelectOption<T>) => void;
115
121
  }
@@ -178,18 +184,15 @@ export interface ISliderProps {
178
184
  onUpdate?: (value: number | [number, number]) => void;
179
185
  }
180
186
  export interface ITextFieldProps {
181
- id?: {
182
- name?: string;
183
- value?: string;
184
- };
187
+ id?: string;
185
188
  wrapperClass?: string;
186
189
  label?: {
187
190
  name?: string;
188
- class?: string;
191
+ bold?: boolean;
192
+ italic?: boolean;
193
+ color?: string;
189
194
  };
190
- type?: 'small' | 'medium' | 'xlarge';
191
- bold?: boolean;
192
- italic?: boolean;
195
+ type?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' | 'huge' | 'massive';
193
196
  }
194
197
  export interface IProgressBarProps {
195
198
  id?: {
@@ -269,9 +272,9 @@ export interface ITableProps<T extends object> {
269
272
  name?: string;
270
273
  class?: string;
271
274
  };
272
- tableHeader: ITableHeader<T>[];
273
- tableBody: T[];
274
- info?: string;
275
+ header: ITableHeader<T>[];
276
+ body: T[];
277
+ footer?: string;
275
278
  cursor?: string | null;
276
279
  loader?: Writable<boolean>;
277
280
  getData?: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-svelte-ui-lib",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -37,12 +37,13 @@
37
37
  "typescript": "^5.9.3"
38
38
  },
39
39
  "devDependencies": {
40
- "@sveltejs/kit": "^2.43.7",
40
+ "@sveltejs/kit": "^2.44.0",
41
41
  "@sveltejs/package": "^2.5.4",
42
42
  "@sveltejs/vite-plugin-svelte": "^6.2.1",
43
- "publint": "^0.3.13",
44
- "svelte": "^5.39.8",
43
+ "publint": "^0.3.14",
44
+ "svelte": "^5.39.9",
45
45
  "svelte-preprocess": "^6.0.3",
46
- "vite": "^7.1.9"
46
+ "vite": "^7.1.9",
47
+ "vite-plugin-compression": "^0.5.1"
47
48
  }
48
49
  }