poe-svelte-ui-lib 1.6.1 → 1.6.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.
@@ -1,21 +1,22 @@
1
1
  <!-- $lib/ElementsUI/Table.svelte -->
2
2
  <script lang="ts">
3
- import { get } from 'svelte/store'
4
- import type { ITableHeader, ITableProps } from '../types'
5
- import { fade, fly } from 'svelte/transition'
6
- import { twMerge } from 'tailwind-merge'
7
- import { onMount } from 'svelte'
8
- import ButtonClear from '../libIcons/ButtonClear.svelte'
3
+ import { get } from "svelte/store"
4
+ import type { ISelectOption, ITableHeader, ITableProps } from "../types"
5
+ import { fade, fly, slide } from "svelte/transition"
6
+ import { twMerge } from "tailwind-merge"
7
+ import { onMount } from "svelte"
8
+ import ButtonClear from "../libIcons/ButtonClear.svelte"
9
+ import { t } from "../locales/i18n"
9
10
 
10
11
  let {
11
12
  id = crypto.randomUUID(),
12
- wrapperClass = '',
13
- label = { name: '', class: '' },
13
+ wrapperClass = "",
14
+ label = { name: "", class: "" },
14
15
  body = $bindable(),
15
16
  header = [],
16
- footer = '',
17
- dataBuffer = { stashData: false, rowsAmmount: 10, clearButton: false, clearClass: '' },
18
- type = 'table',
17
+ footer = "",
18
+ dataBuffer = { stashData: false, rowsAmmount: 10, clearButton: false, clearClass: "" },
19
+ type = "table",
19
20
  outline = false,
20
21
  cursor = null,
21
22
  loader,
@@ -33,7 +34,7 @@
33
34
  /* Сортировка */
34
35
  let sortState: {
35
36
  key: string | null
36
- direction: 'asc' | 'desc' | null
37
+ direction: "asc" | "desc" | null
37
38
  } = {
38
39
  key: null,
39
40
  direction: null,
@@ -42,42 +43,42 @@
42
43
  let isAutoscroll = $state(false)
43
44
 
44
45
  const logTypeOptions = [
45
- { id: crypto.randomUUID(), name: 'Error', value: 'error', color: 'bg-(--red-color)' },
46
- { id: crypto.randomUUID(), name: 'Warning', value: 'warning', color: 'bg-(--yellow-color)' },
47
- { id: crypto.randomUUID(), name: 'Info', value: 'info', color: 'bg-(--gray-color)' },
46
+ { id: crypto.randomUUID(), name: "Error", value: "error", color: "bg-(--red-color)" },
47
+ { id: crypto.randomUUID(), name: "Warning", value: "warning", color: "bg-(--yellow-color)" },
48
+ { id: crypto.randomUUID(), name: "Info", value: "info", color: "bg-(--gray-color)" },
48
49
  ]
49
- let logType = $state(['error', 'warning'])
50
+ let logType = $state(["error", "warning"])
50
51
 
51
52
  /* Сортировка столбцов */
52
53
  const sortRows = (key: string) => {
53
54
  if (sortState.key === key) {
54
- sortState.direction = sortState.direction === 'asc' ? 'desc' : 'asc'
55
+ sortState.direction = sortState.direction === "asc" ? "desc" : "asc"
55
56
  } else {
56
57
  sortState.key = key
57
- sortState.direction = 'asc'
58
+ sortState.direction = "asc"
58
59
  }
59
60
 
60
61
  body = [...body].sort((a, b) => {
61
62
  const aValue = a[key]
62
63
  const bValue = b[key]
63
- if (typeof aValue === 'number' && typeof bValue === 'number') {
64
- return sortState.direction === 'asc' ? aValue - bValue : bValue - aValue
64
+ if (typeof aValue === "number" && typeof bValue === "number") {
65
+ return sortState.direction === "asc" ? aValue - bValue : bValue - aValue
65
66
  }
66
67
  if (aValue instanceof Date && bValue instanceof Date) {
67
- return sortState.direction === 'asc' ? aValue.getTime() - bValue.getTime() : bValue.getTime() - aValue.getTime()
68
+ return sortState.direction === "asc" ? aValue.getTime() - bValue.getTime() : bValue.getTime() - aValue.getTime()
68
69
  }
69
70
  const strA = String(aValue).toLowerCase()
70
71
  const strB = String(bValue).toLowerCase()
71
- const numA = strA.match(/\d+/g)?.[0] || ''
72
- const numB = strB.match(/\d+/g)?.[0] || ''
72
+ const numA = strA.match(/\d+/g)?.[0] || ""
73
+ const numB = strB.match(/\d+/g)?.[0] || ""
73
74
  if (numA && numB) {
74
75
  const numCompare = parseInt(numA, 10) - parseInt(numB, 10)
75
76
  if (numCompare !== 0) {
76
- return sortState.direction === 'asc' ? numCompare : -numCompare
77
+ return sortState.direction === "asc" ? numCompare : -numCompare
77
78
  }
78
79
  }
79
80
  const stringCompare = strA.localeCompare(strB)
80
- return sortState.direction === 'asc' ? stringCompare : -stringCompare
81
+ return sortState.direction === "asc" ? stringCompare : -stringCompare
81
82
  })
82
83
  }
83
84
 
@@ -113,18 +114,33 @@
113
114
  if (button.onClick) button.onClick(row)
114
115
  else if (button.eventHandler && onClick) {
115
116
  let value: Record<string, boolean | string | number | number[] | object | null> = {}
116
- button.eventHandler.Variables.forEach((v: string) => {
117
- value[v] = row[v]
118
- })
117
+ button.eventHandler.Variables.forEach((v: string) => (value[v] = row[v]))
119
118
  button.eventHandler.Value = JSON.stringify(value)
120
119
  onClick(button.eventHandler)
121
120
  }
122
121
  }
123
122
 
124
- let copiedCell = $state({ x: '', y: -1 })
123
+ let isDropdownOpen: number | null = $state(null)
124
+ let changedOptions: { index: number; options: ISelectOption<string | number>[] | null }[] = $state([])
125
+
126
+ const selectOption = (index: number, options: ISelectOption<string | number>[], option: ISelectOption<string | number>, event: MouseEvent) => {
127
+ event.stopPropagation()
128
+
129
+ const existingItem = changedOptions.find(item => item.index === index)
130
+
131
+ if (existingItem) {
132
+ existingItem.options = [option, ...options.filter(opt => opt.id !== option.id)]
133
+ } else {
134
+ changedOptions = [...changedOptions, { index, options: [option, ...options.filter(opt => opt.id !== option.id)] }]
135
+ }
136
+
137
+ isDropdownOpen = null
138
+ }
139
+
140
+ let copiedCell = $state({ x: "", y: -1 })
125
141
  let tooltip = $state({
126
142
  show: false,
127
- text: '',
143
+ text: "",
128
144
  x: 0,
129
145
  y: 0,
130
146
  })
@@ -133,14 +149,14 @@
133
149
  modalData = {
134
150
  isOpen: true,
135
151
  rawData: text,
136
- formattedData: formatting ? formatting(text) : (text ?? ''),
152
+ formattedData: formatting ? formatting(text) : (text ?? ""),
137
153
  }
138
154
  }
139
155
 
140
156
  const showTooltip = (event: MouseEvent, text: string, formatting?: (text: string) => string) => {
141
157
  tooltip = {
142
158
  show: true,
143
- text: formatting ? formatting(text) : (text ?? ''),
159
+ text: formatting ? formatting(text) : (text ?? ""),
144
160
  x: event.clientX,
145
161
  y: event.clientY,
146
162
  }
@@ -153,23 +169,23 @@
153
169
  /* Для работы этой проверки в описании столбцов таблицы нужно явно указать что строка будет пустая при отсутствии иконки в БД -
154
170
  src: (row) => (row.icon ? `data:image/png;base64,${row.icon}` : '') */
155
171
  const hasImage = (column: ITableHeader<any>, row: any): boolean => {
156
- const src = typeof column.image?.src === 'function' ? column.image.src(row) : column.image?.src
172
+ const src = typeof column.image?.src === "function" ? column.image.src(row) : column.image?.src
157
173
  return !!src
158
174
  }
159
175
 
160
176
  $effect(() => {
161
177
  const currentType = type
162
- if (currentType === 'logger') {
178
+ if (currentType === "logger") {
163
179
  header = [
164
180
  {
165
- key: 'color',
166
- label: { name: 'Type' },
167
- width: '3rem',
181
+ key: "color",
182
+ label: { name: "Type" },
183
+ width: "3rem",
168
184
  } as ITableHeader<any>,
169
185
  {
170
- key: 'data',
171
- label: { name: 'Data' },
172
- width: 'calc(100% - 3rem)',
186
+ key: "data",
187
+ label: { name: "Data" },
188
+ width: "calc(100% - 3rem)",
173
189
  } as ITableHeader<any>,
174
190
  ]
175
191
  }
@@ -179,14 +195,14 @@
179
195
  })
180
196
 
181
197
  $effect(() => {
182
- if (body && type == 'logger') {
198
+ if (body && type == "logger") {
183
199
  if (Array.isArray(body)) {
184
200
  for (let i = 0; i < body.length; i++) {
185
201
  buffer = [
186
202
  ...buffer,
187
203
  {
188
204
  type: Object.entries(body[i])[0][1] as string,
189
- color: `<div class='size-6 rounded-full ${logTypeOptions.find((o) => o.value == Object.entries(body[i])[0][1])?.color}'></div>`,
205
+ color: `<div class='size-6 rounded-full ${logTypeOptions.find(o => o.value == Object.entries(body[i])[0][1])?.color}'></div>`,
190
206
  data: Object.entries(body[i])[1][1] as string,
191
207
  },
192
208
  ]
@@ -196,7 +212,7 @@
196
212
  ...buffer,
197
213
  {
198
214
  type: Object.entries(body)[0][1] as string,
199
- color: `<div class='size-6 rounded-full ${logTypeOptions.find((o) => o.value == Object.entries(body)[0][1])?.color}'></div>`,
215
+ color: `<div class='size-6 rounded-full ${logTypeOptions.find(o => o.value == Object.entries(body)[0][1])?.color}'></div>`,
200
216
  data: Object.entries(body)[1][1] as string,
201
217
  },
202
218
  ]
@@ -211,13 +227,12 @@
211
227
  })
212
228
 
213
229
  $effect(() => {
214
- if (body && dataBuffer.stashData && type == 'table') {
230
+ if (body && dataBuffer.stashData && type == "table") {
215
231
  if (Array.isArray(body)) {
216
232
  for (let i = 0; i < body.length; i++) {
217
233
  buffer = [...buffer, body[i]]
218
234
  }
219
235
  } else buffer = [...buffer, body]
220
- buffer = [...buffer, body]
221
236
  if (buffer.length > (dataBuffer.rowsAmmount ?? 10)) {
222
237
  buffer = buffer.slice(-(dataBuffer.rowsAmmount ?? 10))
223
238
  }
@@ -228,28 +243,28 @@
228
243
 
229
244
  onMount(() => {
230
245
  if (autoscroll) {
231
- container?.addEventListener('scroll', handleAutoScroll)
246
+ container?.addEventListener("scroll", handleAutoScroll)
232
247
  scrollToBottom()
233
248
  }
234
249
 
235
- if (type === 'logger') {
250
+ if (type === "logger") {
236
251
  header = [
237
252
  {
238
- key: 'color',
239
- label: { name: 'Type' },
240
- width: '3rem',
253
+ key: "color",
254
+ label: { name: "Type" },
255
+ width: "3rem",
241
256
  } as ITableHeader<any>,
242
257
  {
243
- key: 'data',
244
- label: { name: 'Data' },
245
- width: 'calc(100% - 3rem)',
258
+ key: "data",
259
+ label: { name: "Data" },
260
+ width: "calc(100% - 3rem)",
246
261
  } as ITableHeader<any>,
247
262
  ]
248
263
  }
249
264
 
250
265
  return () => {
251
266
  if (autoscroll) {
252
- container?.removeEventListener('scroll', handleAutoScroll)
267
+ container?.removeEventListener("scroll", handleAutoScroll)
253
268
  }
254
269
  }
255
270
  })
@@ -257,13 +272,12 @@
257
272
 
258
273
  <div
259
274
  id={`${id}-${crypto.randomUUID().slice(0, 6)}`}
260
- class={twMerge(`bg-blue flex h-full w-full items-center ${type == 'logger' ? 'gap-2' : ''} flex-col overflow-hidden`, wrapperClass)}
261
- >
275
+ class={twMerge(`bg-blue flex h-full w-full items-center ${type == "logger" ? "gap-2" : ""} flex-col overflow-hidden`, wrapperClass)}>
262
276
  {#if label.name}
263
277
  <h5 class={twMerge(`w-full px-4 text-center`, label.class)}>{label.name}</h5>
264
278
  {/if}
265
279
 
266
- {#if type == 'logger'}
280
+ {#if type == "logger"}
267
281
  <div id={`${id}-${crypto.randomUUID().slice(0, 6)}`} class="flex w-[50%] justify-center rounded-full">
268
282
  {#each logTypeOptions as option, index}
269
283
  <button
@@ -272,20 +286,17 @@
272
286
  select-none hover:shadow-md
273
287
  ${
274
288
  logType.includes(option.value) && logType !== null
275
- ? 'z-10 py-1 shadow-[0_0_10px_var(--shadow-color)] hover:shadow-[0_0_15px_var(--shadow-color)]'
276
- : ''
289
+ ? "z-10 py-1 shadow-[0_0_10px_var(--shadow-color)] hover:shadow-[0_0_15px_var(--shadow-color)]"
290
+ : ""
277
291
  }
278
- ${logTypeOptions.length > 0 && index === 0 ? 'rounded-l-2xl' : ''} ${
279
- index === logTypeOptions.length - 1 ? 'rounded-r-2xl' : ''
280
- } ${option.color}`)}
292
+ ${logTypeOptions.length > 0 && index === 0 ? "rounded-l-2xl" : ""} ${index === logTypeOptions.length - 1 ? "rounded-r-2xl" : ""} ${option.color}`)}
281
293
  onclick={() => {
282
294
  if (logType.includes(option.value)) {
283
- logType = logType.filter((type) => type !== option.value)
295
+ logType = logType.filter(type => type !== option.value)
284
296
  } else {
285
297
  logType.push(option.value)
286
298
  }
287
- }}
288
- >
299
+ }}>
289
300
  <span class="flex flex-row items-center justify-center gap-4">
290
301
  {#if option}
291
302
  <div class="flex-1">
@@ -301,29 +312,26 @@
301
312
  <div
302
313
  class="relative flex h-full w-full flex-col overflow-hidden rounded-xl border shadow-sm transition duration-200 hover:shadow-md {outline
303
314
  ? ' border-(--border-color)'
304
- : 'border-transparent'} "
305
- >
315
+ : 'border-transparent'} ">
306
316
  <!-- Table Header -->
307
- <div class="grid font-semibold" style={`grid-template-columns: ${header.map((c) => c.width || 'minmax(0, 1fr)').join(' ')};`}>
317
+ <div class="grid font-semibold" style={`grid-template-columns: ${header.map(c => c.width || "minmax(0, 1fr)").join(" ")};`}>
308
318
  {#each header as column, index (column)}
309
319
  <div
310
320
  class={twMerge(
311
- `items-center justify-center border-l ${outline && index !== 0 ? ' border-(--border-color)' : 'border-transparent'} ${
312
- column.align === 'center'
313
- ? 'flex justify-center text-center'
314
- : column.align === 'right'
315
- ? 'flex justify-end text-right'
316
- : 'flex justify-start text-left'
321
+ `items-center justify-center border-l ${outline && index !== 0 ? " border-(--border-color)" : "border-transparent"} ${
322
+ column.align === "center"
323
+ ? "flex justify-center text-center"
324
+ : column.align === "right"
325
+ ? "flex justify-end text-right"
326
+ : "flex justify-start text-left"
317
327
  } gap-1 bg-(--bg-color) p-2 text-left`,
318
328
  column.label?.class,
319
- )}
320
- >
329
+ )}>
321
330
  <span>{column.label?.name}</span>
322
331
  {#if column.sortable}
323
332
  <button
324
333
  class="inline-block cursor-pointer font-bold transition-transform duration-75 hover:scale-110 active:scale-95"
325
- onclick={() => sortRows(column.key as string)}
326
- >
334
+ onclick={() => sortRows(column.key as string)}>
327
335
  ↑↓
328
336
  </button>
329
337
  {/if}
@@ -333,11 +341,10 @@
333
341
  {#if dataBuffer.clearButton}
334
342
  <button
335
343
  class={twMerge(
336
- 'absolute right-2 bg-(--back-color) rounded-full p-1 cursor-pointer [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full',
344
+ "absolute right-2 bg-(--back-color) rounded-full p-1 cursor-pointer [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full",
337
345
  dataBuffer.clearClass,
338
346
  )}
339
- onclick={clearBuffer}
340
- >
347
+ onclick={clearBuffer}>
341
348
  <ButtonClear />
342
349
  </button>
343
350
  {/if}
@@ -345,14 +352,14 @@
345
352
  {#if body || buffer}
346
353
  {@const isSliced = buffer.length - (dataBuffer.rowsAmmount ?? 10) > 0 ? buffer.length - ((dataBuffer.rowsAmmount ?? 10) % 2) !== 0 : false}
347
354
  {@const rows =
348
- type == 'logger'
349
- ? buffer.filter((str) => logType.includes(str.type)).slice(-(dataBuffer.rowsAmmount ?? 10))
355
+ type == "logger"
356
+ ? buffer.filter(str => logType.includes(str.type)).slice(-(dataBuffer.rowsAmmount ?? 10))
350
357
  : dataBuffer.stashData
351
358
  ? buffer.slice(-(dataBuffer.rowsAmmount ?? 10))
352
359
  : body}
353
360
  <!-- Table Body с прокруткой -->
354
361
  <div class="flex-1 overflow-y-auto bg-(--container-color)/50" bind:this={container} onscroll={handleScroll}>
355
- <div class="grid min-w-0" style={`grid-template-columns: ${header.map((c) => c.width || 'minmax(0, 1fr)').join(' ')};`}>
362
+ <div class="grid min-w-0" style={`grid-template-columns: ${header.map(c => c.width || "minmax(0, 1fr)").join(" ")};`}>
356
363
  {#each rows as row, index (row)}
357
364
  {#each header as column, j (column)}
358
365
  <div
@@ -365,35 +372,70 @@
365
372
  : 'flex justify-start text-left'}
366
373
  border-t
367
374
  {j !== 0 ? ' border-l ' : ''}
368
- {outline ? 'border-(--border-color)' : 'border-transparent'} "
369
- >
370
- {#if column.buttons}
375
+ {outline ? 'border-(--border-color)' : 'border-transparent'} ">
376
+ {#if column.action?.type == "buttons" && column.action?.buttons}
371
377
  <div class="flex w-full flex-col gap-1">
372
- {#each column.buttons as button (button)}
378
+ {#each column.action?.buttons as button (button)}
373
379
  <button
374
380
  class="{twMerge(`cursor-pointer rounded-full
375
381
  px-4 py-1 font-semibold shadow-sm transition-shadow duration-200 outline-none select-none hover:shadow-md
376
382
  ${typeof button.class === 'function' ? button.class(row) : button.class}`)} bg-(--bg-color)"
377
- onclick={() => buttonClick(row, button)}
378
- >
379
- {typeof button.name === 'function' ? button.name(row) : button.name}
383
+ onclick={() => buttonClick(row, button)}>
384
+ {typeof button.name === "function" ? button.name(row) : button.name}
380
385
  </button>
381
386
  {/each}
382
387
  </div>
388
+ {:else if column.action?.type == "select" && column.action?.select}
389
+ {@const currentOptions = changedOptions.find(item => item.index === index)?.options}
390
+ {@const defaultOptions = Array.isArray(row[column.key])
391
+ ? row[column.key].map((option: string | number) => ({
392
+ id: crypto.randomUUID(),
393
+ value: option,
394
+ name: option,
395
+ class: "",
396
+ disabled: false,
397
+ }))
398
+ : []}
399
+ {@const options = currentOptions || defaultOptions}
400
+ <div class="relative w-full">
401
+ <button
402
+ class={`w-full rounded-2xl border border-(--blue-color) bg-(--back-color) p-1 text-center shadow-[0_0_3px_rgb(0_0_0_/0.25)] transition duration-200
403
+ cursor-pointer hover:shadow-[0_0_6px_rgb(0_0_0_/0.25)]`}
404
+ onclick={() => (isDropdownOpen = isDropdownOpen === index ? null : index)}>
405
+ {options[0]?.name || $t("common.select_tag")}
406
+ </button>
407
+
408
+ {#if isDropdownOpen === index}
409
+ <div
410
+ class="absolute top-full left-1/2 z-50 -translate-x-1/2 rounded-b-2xl shadow-[0_0_3px_rgb(0_0_0_/0.25)]"
411
+ style="width: calc(100% - 1.8rem);"
412
+ transition:slide={{ duration: 250 }}>
413
+ {#each options as option, option_index (option.id)}
414
+ <button
415
+ id={option.id}
416
+ value={option?.value ? String(option.value) : ""}
417
+ class={twMerge(
418
+ `flex h-full w-full cursor-pointer items-center justify-center p-1 inset-shadow-[0_10px_10px_-15px_rgb(0_0_0_/0.5)] duration-250 hover:bg-(--field-color)! bg-(--back-color)
419
+ ${option_index === options.length - 1 ? "rounded-b-2xl" : ""} `,
420
+ option.class,
421
+ )}
422
+ onclick={e => selectOption(index, options, option, e)}>
423
+ {option.name}
424
+ </button>
425
+ {/each}
426
+ </div>
427
+ {/if}
428
+ </div>
383
429
  {:else if column.image?.src || column.image?.defaultIcon}
384
- <div
385
- class="flex items-center justify-center"
386
- style={`width: ${column.image.width || '5rem'}; height: ${column.image.height || '5rem'};`}
387
- >
430
+ <div class="flex items-center justify-center" style={`width: ${column.image.width || "5rem"}; height: ${column.image.height || "5rem"};`}>
388
431
  {#if hasImage(column, row)}
389
432
  <img
390
- src={typeof column.image?.src === 'function' ? column.image.src(row) : column.image?.src || ''}
391
- alt={column.image.alt ?? 'Image'}
392
- class={twMerge(`h-full w-full object-cover ${column.image.class || ''}`)}
393
- loading="lazy"
394
- />
433
+ src={typeof column.image?.src === "function" ? column.image.src(row) : column.image?.src || ""}
434
+ alt={column.image.alt ?? "Image"}
435
+ class={twMerge(`h-full w-full object-cover ${column.image.class || ""}`)}
436
+ loading="lazy" />
395
437
  {:else if column.image.defaultIcon}
396
- {#if typeof column.image.defaultIcon === 'string'}
438
+ {#if typeof column.image.defaultIcon === "string"}
397
439
  {@html column.image.defaultIcon}
398
440
  {:else}
399
441
  <column.image.defaultIcon />
@@ -403,25 +445,23 @@
403
445
  {:else}
404
446
  <div
405
447
  class=" w-full max-w-full wrap-break-word {column.overflow?.truncated ? 'truncate' : ' whitespace-normal'}"
406
- onmouseenter={column.overflow?.truncated ? (e) => showTooltip(e, row[column.key], column.overflow?.formatting) : undefined}
448
+ onmouseenter={column.overflow?.truncated ? e => showTooltip(e, row[column.key], column.overflow?.formatting) : undefined}
407
449
  onmouseleave={column.overflow?.truncated ? hideTooltip : undefined}
408
450
  onmousemove={column.overflow?.truncated
409
- ? (e) => {
451
+ ? e => {
410
452
  tooltip.x = e.clientX
411
453
  tooltip.y = e.clientY
412
454
  }
413
455
  : undefined}
414
456
  role="columnheader"
415
- tabindex={null}
416
- >
457
+ tabindex={null}>
417
458
  {#if column.overflow?.modal}
418
459
  <button
419
460
  class="w-full cursor-pointer overflow-hidden text-left text-ellipsis whitespace-nowrap"
420
- onclick={(e) => {
461
+ onclick={e => {
421
462
  e.stopPropagation()
422
463
  showModal(row[column.key], column.overflow?.formatting)
423
- }}
424
- >
464
+ }}>
425
465
  {@html row[column.key]}
426
466
  </button>
427
467
  {:else}
@@ -435,28 +475,25 @@
435
475
  {#if column.overflow?.copy}
436
476
  <button
437
477
  class="mx-2 flex cursor-pointer border-none bg-transparent text-2xl"
438
- onclick={(e) => {
478
+ onclick={e => {
439
479
  e.preventDefault()
440
480
  navigator.clipboard.writeText(row[column.key])
441
481
  copiedCell = { x: column.key as string, y: index }
442
- setTimeout(() => (copiedCell = { x: '', y: -1 }), 1000)
482
+ setTimeout(() => (copiedCell = { x: "", y: -1 }), 1000)
443
483
  }}
444
- aria-label="Копировать текст"
445
- >
484
+ aria-label="Копировать текст">
446
485
  <div class=" size-5 text-sm [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full">
447
486
  {#if copiedCell.y === index && copiedCell.x === column.key}
448
487
  <div
449
488
  class="absolute top-1/2 right-3.5 -translate-y-1/2 transform rounded-md bg-(--green-color) px-1.5 py-1 shadow-lg"
450
- transition:fade={{ duration: 200 }}
451
- >
489
+ transition:fade={{ duration: 200 }}>
452
490
 
453
491
  </div>
454
492
  {:else}
455
493
  <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
456
494
  <g fill="none" stroke="currentColor" stroke-width="1.5">
457
495
  <path
458
- 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"
459
- />
496
+ 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" />
460
497
  <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" />
461
498
  </g>
462
499
  </svg>
@@ -478,8 +515,7 @@
478
515
  style="background: color-mix(in srgb, var(--yellow-color) 30%, var(--back-color)); transform: translateX(-50%); left: {tooltip.x +
479
516
  10}px; top: {tooltip.y + 10}px;"
480
517
  transition:fly={{ y: 10, duration: 200 }}
481
- role="tooltip"
482
- >
518
+ role="tooltip">
483
519
  {@html tooltip.text}
484
520
  </div>
485
521
  {/if}
@@ -1,4 +1,4 @@
1
- import type { ITableProps } from '../types';
1
+ import type { ITableProps } from "../types";
2
2
  declare const Table: import("svelte").Component<ITableProps<any>, {
3
3
  clearBuffer: () => void;
4
4
  }, "body" | "modalData">;