spaper 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/README.md +20 -58
  2. package/dist/components/Alert.svelte +83 -0
  3. package/dist/components/Alert.svelte.d.ts +15 -0
  4. package/dist/components/Article.svelte +63 -0
  5. package/dist/components/Article.svelte.d.ts +17 -0
  6. package/dist/components/Avatar/Avatar.svelte +102 -0
  7. package/dist/components/Avatar/Avatar.svelte.d.ts +16 -0
  8. package/dist/components/Avatar/AvatarGroup.svelte +21 -0
  9. package/dist/components/Avatar/AvatarGroup.svelte.d.ts +9 -0
  10. package/dist/components/Avatar/index.d.ts +2 -0
  11. package/dist/components/Avatar/index.js +2 -0
  12. package/dist/components/Breadcrumb.svelte +33 -0
  13. package/dist/components/Breadcrumb.svelte.d.ts +12 -0
  14. package/dist/components/Button.svelte +174 -0
  15. package/dist/components/Button.svelte.d.ts +33 -0
  16. package/dist/components/Card.svelte +101 -0
  17. package/dist/components/Card.svelte.d.ts +22 -0
  18. package/dist/components/Carousel/Carousel.svelte +204 -0
  19. package/dist/components/Carousel/Carousel.svelte.d.ts +27 -0
  20. package/dist/components/Carousel/CarouselItem.svelte +48 -0
  21. package/dist/components/Carousel/CarouselItem.svelte.d.ts +7 -0
  22. package/{components → dist/components}/Carousel/index.d.ts +1 -0
  23. package/dist/components/Carousel/types.d.ts +22 -0
  24. package/dist/components/CloseButton.svelte +34 -0
  25. package/dist/components/CloseButton.svelte.d.ts +8 -0
  26. package/dist/components/Collapsible.svelte +64 -0
  27. package/dist/components/Collapsible.svelte.d.ts +16 -0
  28. package/dist/components/CopyButton.svelte +54 -0
  29. package/dist/components/CopyButton.svelte.d.ts +13 -0
  30. package/dist/components/Divider.svelte +9 -0
  31. package/dist/components/Divider.svelte.d.ts +6 -0
  32. package/dist/components/Form/Checkbox.svelte +54 -0
  33. package/dist/components/Form/Checkbox.svelte.d.ts +15 -0
  34. package/dist/components/Form/Input.svelte +105 -0
  35. package/dist/components/Form/Input.svelte.d.ts +21 -0
  36. package/dist/components/Form/NumberInput/DecrementButton.svelte +14 -0
  37. package/dist/components/Form/NumberInput/DecrementButton.svelte.d.ts +9 -0
  38. package/dist/components/Form/NumberInput/IncrementButton.svelte +14 -0
  39. package/dist/components/Form/NumberInput/IncrementButton.svelte.d.ts +9 -0
  40. package/dist/components/Form/NumberInput/NumberInput.svelte +227 -0
  41. package/dist/components/Form/NumberInput/NumberInput.svelte.d.ts +34 -0
  42. package/dist/components/Form/NumberInput/index.d.ts +3 -0
  43. package/dist/components/Form/NumberInput/index.js +3 -0
  44. package/dist/components/Form/Radio.svelte +42 -0
  45. package/dist/components/Form/Radio.svelte.d.ts +13 -0
  46. package/dist/components/Form/Select.svelte +61 -0
  47. package/dist/components/Form/Select.svelte.d.ts +12 -0
  48. package/dist/components/Form/Slider.svelte +129 -0
  49. package/dist/components/Form/Slider.svelte.d.ts +22 -0
  50. package/dist/components/Form/Switch.svelte +101 -0
  51. package/dist/components/Form/Switch.svelte.d.ts +22 -0
  52. package/dist/components/Form/index.d.ts +9 -0
  53. package/{components → dist/components}/Form/index.js +2 -2
  54. package/dist/components/Hero.svelte +78 -0
  55. package/dist/components/Hero.svelte.d.ts +17 -0
  56. package/dist/components/Icon.svelte +102 -0
  57. package/dist/components/Icon.svelte.d.ts +27 -0
  58. package/dist/components/Modal/Modal.svelte +120 -0
  59. package/dist/components/Modal/Modal.svelte.d.ts +19 -0
  60. package/dist/components/Modal/index.d.ts +12 -0
  61. package/dist/components/Modal/index.js +30 -0
  62. package/dist/components/Navbar.svelte +98 -0
  63. package/dist/components/Navbar.svelte.d.ts +11 -0
  64. package/dist/components/Pagination/Arrow.svelte +29 -0
  65. package/dist/components/Pagination/Arrow.svelte.d.ts +8 -0
  66. package/dist/components/Pagination/NavigationButton.svelte +33 -0
  67. package/dist/components/Pagination/NavigationButton.svelte.d.ts +13 -0
  68. package/dist/components/Pagination/Pagination.svelte +209 -0
  69. package/dist/components/Pagination/Pagination.svelte.d.ts +32 -0
  70. package/{components → dist/components}/Pagination/arrow-dimension.js +3 -3
  71. package/{components → dist/components}/Pagination/index.d.ts +1 -1
  72. package/dist/components/Popover.svelte +64 -0
  73. package/dist/components/Popover.svelte.d.ts +17 -0
  74. package/dist/components/Progress.svelte +87 -0
  75. package/dist/components/Progress.svelte.d.ts +19 -0
  76. package/dist/components/ScrollTop.svelte +79 -0
  77. package/dist/components/ScrollTop.svelte.d.ts +17 -0
  78. package/dist/components/Skeleton.svelte +104 -0
  79. package/dist/components/Skeleton.svelte.d.ts +21 -0
  80. package/dist/components/Spinner.svelte +59 -0
  81. package/dist/components/Spinner.svelte.d.ts +16 -0
  82. package/dist/components/Table/Table.svelte +292 -0
  83. package/dist/components/Table/Table.svelte.d.ts +25 -0
  84. package/dist/components/Table/TableColumn.svelte +62 -0
  85. package/dist/components/Table/TableColumn.svelte.d.ts +15 -0
  86. package/dist/components/Table/context.d.ts +13 -0
  87. package/dist/components/Table/context.js +1 -0
  88. package/dist/components/Table/index.d.ts +2 -0
  89. package/dist/components/Table/index.js +2 -0
  90. package/dist/components/Tabs/Tab.svelte +90 -0
  91. package/dist/components/Tabs/Tab.svelte.d.ts +14 -0
  92. package/dist/components/Tabs/Tabs.svelte +138 -0
  93. package/dist/components/Tabs/Tabs.svelte.d.ts +13 -0
  94. package/{components → dist/components}/Tabs/utils.d.ts +4 -3
  95. package/dist/components/Tag.svelte +38 -0
  96. package/dist/components/Tag.svelte.d.ts +10 -0
  97. package/dist/components/Toast/Toast.svelte +105 -0
  98. package/dist/components/Toast/Toast.svelte.d.ts +6 -0
  99. package/dist/components/Toast/ToastContainer.svelte +101 -0
  100. package/dist/components/Toast/ToastContainer.svelte.d.ts +8 -0
  101. package/{components → dist/components}/Toast/index.d.ts +19 -5
  102. package/dist/components/Toast/index.js +100 -0
  103. package/dist/icons.d.ts +3 -0
  104. package/dist/icons.js +2 -0
  105. package/dist/index.d.ts +31 -0
  106. package/{index.js → dist/index.js} +10 -5
  107. package/dist/type-icons.d.ts +4 -0
  108. package/dist/type-icons.js +9 -0
  109. package/dist/types.d.ts +29 -0
  110. package/dist/utils.d.ts +16 -0
  111. package/dist/utils.js +44 -0
  112. package/package.json +70 -64
  113. package/components/Alert.svelte +0 -34
  114. package/components/Alert.svelte.d.ts +0 -21
  115. package/components/Article.svelte +0 -39
  116. package/components/Article.svelte.d.ts +0 -26
  117. package/components/Badge.svelte +0 -16
  118. package/components/Badge.svelte.d.ts +0 -20
  119. package/components/Breadcrumb.svelte +0 -17
  120. package/components/Breadcrumb.svelte.d.ts +0 -21
  121. package/components/Button.svelte +0 -41
  122. package/components/Button.svelte.d.ts +0 -30
  123. package/components/Card.svelte +0 -70
  124. package/components/Card.svelte.d.ts +0 -32
  125. package/components/Carousel/Carousel.svelte +0 -128
  126. package/components/Carousel/Carousel.svelte.d.ts +0 -35
  127. package/components/Carousel/CarouselItem.svelte +0 -32
  128. package/components/Carousel/CarouselItem.svelte.d.ts +0 -18
  129. package/components/Carousel/types.d.ts +0 -14
  130. package/components/CloseButton.svelte +0 -23
  131. package/components/CloseButton.svelte.d.ts +0 -19
  132. package/components/Collapsible.svelte +0 -49
  133. package/components/Collapsible.svelte.d.ts +0 -21
  134. package/components/CopyButton.svelte +0 -43
  135. package/components/CopyButton.svelte.d.ts +0 -24
  136. package/components/Form/Checkbox.svelte +0 -37
  137. package/components/Form/Checkbox.svelte.d.ts +0 -26
  138. package/components/Form/Form.svelte +0 -11
  139. package/components/Form/Form.svelte.d.ts +0 -26
  140. package/components/Form/Input.svelte +0 -74
  141. package/components/Form/Input.svelte.d.ts +0 -28
  142. package/components/Form/Radio.svelte +0 -26
  143. package/components/Form/Radio.svelte.d.ts +0 -25
  144. package/components/Form/Select.svelte +0 -40
  145. package/components/Form/Select.svelte.d.ts +0 -24
  146. package/components/Form/Slider.svelte +0 -124
  147. package/components/Form/Slider.svelte.d.ts +0 -30
  148. package/components/Form/Switch.svelte +0 -71
  149. package/components/Form/index.d.ts +0 -9
  150. package/components/Form/style.scss +0 -4
  151. package/components/Hero.svelte +0 -78
  152. package/components/Hero.svelte.d.ts +0 -26
  153. package/components/Layout/Col.svelte +0 -25
  154. package/components/Layout/Col.svelte.d.ts +0 -27
  155. package/components/Layout/Row.svelte +0 -24
  156. package/components/Layout/Row.svelte.d.ts +0 -26
  157. package/components/Layout/index.d.ts +0 -2
  158. package/components/Layout/index.js +0 -2
  159. package/components/Modal/Modal.svelte +0 -62
  160. package/components/Modal/Modal.svelte.d.ts +0 -28
  161. package/components/Modal/index.d.ts +0 -13
  162. package/components/Modal/index.js +0 -17
  163. package/components/Navbar.svelte +0 -40
  164. package/components/Navbar.svelte.d.ts +0 -22
  165. package/components/Pagination/Arrow.svelte +0 -17
  166. package/components/Pagination/Arrow.svelte.d.ts +0 -19
  167. package/components/Pagination/NavigationButton.svelte +0 -23
  168. package/components/Pagination/NavigationButton.svelte.d.ts +0 -23
  169. package/components/Pagination/Pagination.svelte +0 -137
  170. package/components/Pagination/Pagination.svelte.d.ts +0 -36
  171. package/components/Popover.svelte +0 -57
  172. package/components/Popover.svelte.d.ts +0 -25
  173. package/components/Progress.svelte +0 -39
  174. package/components/Progress.svelte.d.ts +0 -25
  175. package/components/Skeleton.svelte +0 -55
  176. package/components/Skeleton.svelte.d.ts +0 -22
  177. package/components/Table.svelte +0 -73
  178. package/components/Table.svelte.d.ts +0 -24
  179. package/components/Tabs/Tab.svelte +0 -52
  180. package/components/Tabs/Tab.svelte.d.ts +0 -20
  181. package/components/Tabs/Tabs.svelte +0 -90
  182. package/components/Tabs/Tabs.svelte.d.ts +0 -25
  183. package/components/Toast/Toast.svelte +0 -91
  184. package/components/Toast/Toast.svelte.d.ts +0 -26
  185. package/components/Toast/ToastContainer.svelte +0 -37
  186. package/components/Toast/ToastContainer.svelte.d.ts +0 -18
  187. package/components/Toast/index.js +0 -37
  188. package/index.d.ts +0 -23
  189. package/types.d.ts +0 -16
  190. package/utils.d.ts +0 -16
  191. package/utils.js +0 -34
  192. /package/{components → dist/components}/Carousel/index.js +0 -0
  193. /package/{components → dist/components}/Carousel/types.js +0 -0
  194. /package/{components → dist/components}/Pagination/arrow-dimension.d.ts +0 -0
  195. /package/{components → dist/components}/Pagination/index.js +0 -0
  196. /package/{components → dist/components}/Tabs/index.d.ts +0 -0
  197. /package/{components → dist/components}/Tabs/index.js +0 -0
  198. /package/{components → dist/components}/Tabs/utils.js +0 -0
  199. /package/{components → dist/components}/style.scss +0 -0
  200. /package/{types.js → dist/types.js} +0 -0
@@ -0,0 +1,13 @@
1
+ import type { Writable } from 'svelte/store';
2
+ export interface RegisteredColumn {
3
+ field: string;
4
+ label: string;
5
+ sortable?: boolean;
6
+ key: object;
7
+ }
8
+ export interface TableContext {
9
+ registerColumn: (col: RegisteredColumn) => void;
10
+ unregisterColumn: (key: object) => void;
11
+ columns: Writable<RegisteredColumn[]>;
12
+ }
13
+ export declare const TABLE_CONTEXT = "paper-table";
@@ -0,0 +1 @@
1
+ export const TABLE_CONTEXT = 'paper-table';
@@ -0,0 +1,2 @@
1
+ export { default as Table } from './Table.svelte';
2
+ export { default as TableColumn } from './TableColumn.svelte';
@@ -0,0 +1,2 @@
1
+ export { default as Table } from './Table.svelte';
2
+ export { default as TableColumn } from './TableColumn.svelte';
@@ -0,0 +1,90 @@
1
+ <script lang="ts">
2
+ import { onDestroy, getContext } from 'svelte'
3
+ import type { Snippet } from 'svelte'
4
+ import type { IconNode } from '../../icons'
5
+ import type { TabDataType } from './utils'
6
+ import { getId } from './utils'
7
+
8
+ interface Props {
9
+ label: string
10
+ /** Icon shown to the left of the header text. */
11
+ icon?: IconNode | null
12
+ children?: Snippet
13
+ header?: Snippet
14
+ class?: string
15
+ [key: string]: unknown
16
+ }
17
+
18
+ let {
19
+ label,
20
+ icon = null,
21
+ children,
22
+ header: headerSnippet,
23
+ class: className = '',
24
+ ...rest
25
+ }: Props = $props()
26
+
27
+ const key = {}
28
+ let active = $state(false)
29
+ let headerEl = $state<HTMLElement | undefined>()
30
+
31
+ const tabsData: TabDataType = getContext('tabs')
32
+
33
+ if (!tabsData) throw new Error('Tab should be nested inside a Tabs')
34
+
35
+ function show() {
36
+ active = true
37
+ }
38
+ function hide() {
39
+ active = false
40
+ }
41
+
42
+ // Register during init (not onMount) so labels exist for SSR + first paint.
43
+ tabsData.tabs.update((tabs) => [
44
+ ...tabs,
45
+ { key, label, header: headerEl, icon, show, hide },
46
+ ])
47
+
48
+ $effect(() => {
49
+ const nextLabel = label
50
+ const nextHeader = headerEl
51
+ const nextIcon = icon
52
+ tabsData.tabs.update((tabs) => {
53
+ const current = tabs.find((t) => t.key === key)
54
+ if (
55
+ !current ||
56
+ (current.label === nextLabel &&
57
+ current.header === nextHeader &&
58
+ current.icon === nextIcon)
59
+ ) {
60
+ return tabs
61
+ }
62
+ return tabs.map((t) =>
63
+ t.key === key
64
+ ? { ...t, label: nextLabel, header: nextHeader, icon: nextIcon }
65
+ : t,
66
+ )
67
+ })
68
+ })
69
+
70
+ onDestroy(() => {
71
+ tabsData.tabs.update((tabs) => tabs.filter((t) => t.key !== key))
72
+ })
73
+ </script>
74
+
75
+ <div
76
+ {...rest}
77
+ class={['tabs-paper-content', { 'block!': active }, className]}
78
+ id={getId(label, 'content')}
79
+ aria-hidden={!active}
80
+ aria-labelledby={getId(label, 'label')}
81
+ role="tabpanel"
82
+ tabindex={active ? 0 : -1}
83
+ >
84
+ {#if headerSnippet}
85
+ <div bind:this={headerEl} style="display: none">
86
+ {@render headerSnippet()}
87
+ </div>
88
+ {/if}
89
+ {@render children?.()}
90
+ </div>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { IconNode } from '../../icons';
3
+ interface Props {
4
+ label: string;
5
+ /** Icon shown to the left of the header text. */
6
+ icon?: IconNode | null;
7
+ children?: Snippet;
8
+ header?: Snippet;
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+ declare const Tab: import("svelte").Component<Props, {}, "">;
13
+ type Tab = ReturnType<typeof Tab>;
14
+ export default Tab;
@@ -0,0 +1,138 @@
1
+ <script lang="ts">
2
+ import { setContext, tick } from 'svelte'
3
+ import { writable } from 'svelte/store'
4
+ import type { TabDataType, iTab } from './utils'
5
+ import type { PaperFlexPlacement } from '../../types'
6
+ import { getId } from './utils'
7
+ import Icon from '../Icon.svelte'
8
+
9
+ interface Props {
10
+ activeTab?: number | string
11
+ placement?: PaperFlexPlacement
12
+ contentAlign?: string
13
+ onchange?: (index: number) => void
14
+ onkeypress?: (e: KeyboardEvent) => void
15
+ children?: import('svelte').Snippet
16
+ [key: string]: any
17
+ }
18
+
19
+ let {
20
+ activeTab = $bindable(0),
21
+ placement = 'spaces',
22
+ contentAlign = 'left',
23
+ onchange,
24
+ onkeypress,
25
+ children,
26
+ ...rest
27
+ }: Props = $props()
28
+
29
+ const placementMap: Record<PaperFlexPlacement, string> = {
30
+ spaces: 'tabs-paper-around',
31
+ edges: 'tabs-paper-between',
32
+ right: 'tabs-paper-end',
33
+ center: 'tabs-paper-center',
34
+ left: 'tabs-paper-start',
35
+ }
36
+
37
+ let placementClass = $derived(placementMap[placement] ?? 'tabs-paper-around')
38
+ let tablist = $state<HTMLDivElement | undefined>()
39
+ let focused = $state(0)
40
+
41
+ const tabs = writable<iTab[]>([])
42
+
43
+ const tabsData: TabDataType = {
44
+ activeTab,
45
+ tabs,
46
+ }
47
+
48
+ setContext('tabs', tabsData)
49
+
50
+ function showContent(index: number) {
51
+ onchange?.(index)
52
+ activeTab = index
53
+ }
54
+
55
+ function selectTab(index: number) {
56
+ focused = index
57
+ showContent(index)
58
+ }
59
+
60
+ async function onTabKeydown(event: KeyboardEvent, index: number) {
61
+ const count = $tabs.length
62
+ if (!count) return
63
+
64
+ let next: number | null = null
65
+ if (event.key === 'ArrowRight') next = (index + 1) % count
66
+ else if (event.key === 'ArrowLeft') next = (index - 1 + count) % count
67
+ else if (event.key === 'Home') next = 0
68
+ else if (event.key === 'End') next = count - 1
69
+ else if (event.key === 'Enter' || event.key === ' ') {
70
+ event.preventDefault()
71
+ showContent(index)
72
+ return
73
+ } else return
74
+
75
+ event.preventDefault()
76
+ focused = next
77
+ await tick()
78
+ tablist?.querySelectorAll<HTMLElement>('[role="tab"]')[next]?.focus()
79
+ }
80
+
81
+ $effect(() => {
82
+ const list = $tabs
83
+ const idx = Number(activeTab)
84
+ if (isNaN(idx)) {
85
+ activeTab = 0
86
+ return
87
+ }
88
+ list.forEach((tab, i) => {
89
+ if (i === idx) tab.show()
90
+ else tab.hide()
91
+ })
92
+ })
93
+
94
+ $effect(() => {
95
+ const idx = Number(activeTab)
96
+ if (!Number.isNaN(idx)) focused = idx
97
+ })
98
+ </script>
99
+
100
+ <div
101
+ {...rest}
102
+ class={['tabs-paper', placementClass, rest.class]}
103
+ style="text-align: {contentAlign}"
104
+ >
105
+ <div bind:this={tablist} role="tablist" aria-orientation="horizontal">
106
+ {#each $tabs as { label, header, icon }, index}
107
+ {@const selected = index == activeTab}
108
+ <div
109
+ class={['tabs-paper-header', { 'tabs-paper-header-active': selected }]}
110
+ id={getId(label, 'label')}
111
+ aria-selected={selected}
112
+ aria-controls={getId(label, 'content')}
113
+ role="tab"
114
+ tabindex={index === focused ? 0 : -1}
115
+ onclick={() => selectTab(index)}
116
+ onkeydown={(event) => onTabKeydown(event, index)}
117
+ {onkeypress}
118
+ >
119
+ {#if icon}
120
+ <span class="inline-flex items-center gap-1.5">
121
+ <Icon name={icon} size={18} />
122
+ {#if header}
123
+ {@html header.innerHTML}
124
+ {:else}
125
+ {label}
126
+ {/if}
127
+ </span>
128
+ {:else if header}
129
+ {@html header.innerHTML}
130
+ {:else}
131
+ {label}
132
+ {/if}
133
+ </div>
134
+ {/each}
135
+ </div>
136
+
137
+ {@render children?.()}
138
+ </div>
@@ -0,0 +1,13 @@
1
+ import type { PaperFlexPlacement } from '../../types';
2
+ interface Props {
3
+ activeTab?: number | string;
4
+ placement?: PaperFlexPlacement;
5
+ contentAlign?: string;
6
+ onchange?: (index: number) => void;
7
+ onkeypress?: (e: KeyboardEvent) => void;
8
+ children?: import('svelte').Snippet;
9
+ [key: string]: any;
10
+ }
11
+ declare const Tabs: import("svelte").Component<Props, {}, "activeTab">;
12
+ type Tabs = ReturnType<typeof Tabs>;
13
+ export default Tabs;
@@ -1,8 +1,10 @@
1
1
  import type { Writable } from 'svelte/store';
2
- interface iTab {
3
- key: Object;
2
+ import type { IconNode } from '../../icons';
3
+ export interface iTab {
4
+ key: object;
4
5
  label: string;
5
6
  header?: HTMLElement;
7
+ icon?: IconNode | null;
6
8
  show: () => void;
7
9
  hide: () => void;
8
10
  }
@@ -11,4 +13,3 @@ export interface TabDataType {
11
13
  tabs: Writable<iTab[]>;
12
14
  }
13
15
  export declare function getId(label: string, part: 'label' | 'content'): string;
14
- export {};
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ import type { PaperType } from '../types'
3
+
4
+ interface Props {
5
+ type?: PaperType
6
+ rounded?: boolean
7
+ children?: import('svelte').Snippet
8
+ [key: string]: any
9
+ }
10
+
11
+ let {
12
+ type = 'primary',
13
+ rounded = false,
14
+ children,
15
+ class: className = '',
16
+ ...rest
17
+ }: Props = $props()
18
+
19
+ const typeClass: Record<PaperType, string> = {
20
+ primary: 'tag-paper-primary',
21
+ secondary: 'tag-paper-secondary',
22
+ success: 'tag-paper-success',
23
+ warning: 'tag-paper-warning',
24
+ danger: 'tag-paper-danger',
25
+ }
26
+ </script>
27
+
28
+ <span
29
+ {...rest}
30
+ class={[
31
+ 'tag-paper',
32
+ typeClass[type],
33
+ { 'rounded-[30%]': rounded },
34
+ className,
35
+ ]}
36
+ >
37
+ {@render children?.()}
38
+ </span>
@@ -0,0 +1,10 @@
1
+ import type { PaperType } from '../types';
2
+ interface Props {
3
+ type?: PaperType;
4
+ rounded?: boolean;
5
+ children?: import('svelte').Snippet;
6
+ [key: string]: any;
7
+ }
8
+ declare const Tag: import("svelte").Component<Props, {}, "">;
9
+ type Tag = ReturnType<typeof Tag>;
10
+ export default Tag;
@@ -0,0 +1,105 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte'
3
+ import { fly, fade } from 'svelte/transition'
4
+ import { typeIcons } from '../../type-icons'
5
+ import type { ToastProps } from './'
6
+ import { computeClasses } from '../../utils'
7
+ import CloseButton from '../CloseButton.svelte'
8
+ import Icon from '../Icon.svelte'
9
+
10
+ let {
11
+ icon = null,
12
+ hideIcon = false,
13
+ title = '',
14
+ message = '',
15
+ content,
16
+ type = 'primary',
17
+ duration = 2000,
18
+ position = 'top',
19
+ pauseOnHover = false,
20
+ dismissible = false,
21
+ indefinite = false,
22
+ closeAriaLabel = 'close',
23
+ class: className = '',
24
+ onClose = null,
25
+ }: ToastProps = $props()
26
+
27
+ const TRANSITION_OUT_DURATION: number = 300
28
+ let active: boolean = $state(false)
29
+ let timeoutId: number
30
+
31
+ let shownIcon = $derived(hideIcon ? null : (icon ?? typeIcons[type]))
32
+
33
+ let classes = $derived([
34
+ 'alert-paper',
35
+ 'relative',
36
+ 'm-0',
37
+ 'shadow-paper',
38
+ 'w-[min(250px,calc(100vw-2rem))]',
39
+ computeClasses('alert-paper', { type }),
40
+ className,
41
+ ])
42
+
43
+ onMount(() => {
44
+ // A local `in:` transition does not run on the first paint. Flip after mount.
45
+ active = true
46
+ if (indefinite) return
47
+ timeoutId = window.setTimeout(() => close(), duration)
48
+ return () => clearTimeout(timeoutId)
49
+ })
50
+
51
+ function pause() {
52
+ if (!pauseOnHover || indefinite) return
53
+ clearTimeout(timeoutId)
54
+ }
55
+
56
+ function dismiss() {
57
+ if (!pauseOnHover || indefinite) return
58
+ close()
59
+ }
60
+
61
+ export function close() {
62
+ if (!active) return
63
+ active = false
64
+ clearTimeout(timeoutId)
65
+ onClose?.()
66
+ }
67
+ </script>
68
+
69
+ {#if active}
70
+ <div
71
+ class={classes}
72
+ onmouseenter={pause}
73
+ onmouseleave={dismiss}
74
+ in:fly={{ y: position.includes('top') ? -100 : 100 }}
75
+ out:fade={{ duration: TRANSITION_OUT_DURATION }}
76
+ role="alert"
77
+ >
78
+ <div
79
+ class={['flex items-start gap-2', { 'pe-6': dismissible || indefinite }]}
80
+ >
81
+ {#if shownIcon}
82
+ <span class={['inline-flex shrink-0', { 'h-7 items-center': title }]}>
83
+ <Icon name={shownIcon} size={22} />
84
+ </span>
85
+ {/if}
86
+ <div>
87
+ {#if title}
88
+ <p class="font-paper-heading text-xl font-bold mb-1">{title}</p>
89
+ {/if}
90
+ {#if content}
91
+ {@render content(close)}
92
+ {:else}
93
+ {@html message}
94
+ {/if}
95
+ </div>
96
+ </div>
97
+ {#if dismissible || indefinite}
98
+ <CloseButton
99
+ class="absolute top-4 right-4"
100
+ ariaLabel={closeAriaLabel}
101
+ onclick={() => close()}
102
+ />
103
+ {/if}
104
+ </div>
105
+ {/if}
@@ -0,0 +1,6 @@
1
+ import type { ToastProps } from './';
2
+ declare const Toast: import("svelte").Component<ToastProps, {
3
+ close: () => void;
4
+ }, "">;
5
+ type Toast = ReturnType<typeof Toast>;
6
+ export default Toast;
@@ -0,0 +1,101 @@
1
+ <script lang="ts" module>
2
+ export const containerClass = 'toast-paper-container'
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import { onMount } from 'svelte'
7
+ import type { ToastPosition } from './'
8
+
9
+ interface Props {
10
+ position?: ToastPosition
11
+ }
12
+
13
+ let { position = 'top' }: Props = $props()
14
+
15
+ let viewportStyle = $state('')
16
+
17
+ onMount(() => {
18
+ const mobile = window.matchMedia('(max-width: 768px)')
19
+
20
+ function sync() {
21
+ if (!mobile.matches) {
22
+ viewportStyle = ''
23
+ return
24
+ }
25
+
26
+ const vv = window.visualViewport
27
+ if (!vv) {
28
+ viewportStyle = ''
29
+ return
30
+ }
31
+
32
+ viewportStyle = [
33
+ `top:${vv.offsetTop}px`,
34
+ `left:${vv.offsetLeft}px`,
35
+ `width:${vv.width}px`,
36
+ `height:${vv.height}px`,
37
+ ].join(';')
38
+ }
39
+
40
+ sync()
41
+
42
+ const vv = window.visualViewport
43
+ vv?.addEventListener('scroll', sync)
44
+ vv?.addEventListener('resize', sync)
45
+ mobile.addEventListener('change', sync)
46
+
47
+ return () => {
48
+ vv?.removeEventListener('scroll', sync)
49
+ vv?.removeEventListener('resize', sync)
50
+ mobile.removeEventListener('change', sync)
51
+ }
52
+ })
53
+ </script>
54
+
55
+ <div class={[containerClass, position]} style={viewportStyle}></div>
56
+
57
+ <style>
58
+ :global(.toast-paper-container:is(.top, .bottom) > div) {
59
+ align-self: center;
60
+ }
61
+ :global(.toast-paper-container:is([class*='right']) > div) {
62
+ align-self: end;
63
+ }
64
+ :global(
65
+ .toast-paper-container:is([class*='left']):not(.top):not(.bottom) > div
66
+ ) {
67
+ align-self: start;
68
+ }
69
+ :global(.toast-paper-container > div) {
70
+ flex-shrink: 0;
71
+ pointer-events: auto;
72
+ }
73
+
74
+ div {
75
+ position: fixed;
76
+ inset-inline: 0;
77
+ display: flex;
78
+ width: 100%;
79
+ max-height: 100vh;
80
+ max-height: 100dvh;
81
+ padding: max(1rem, env(safe-area-inset-top, 0px))
82
+ max(1rem, env(safe-area-inset-right, 0px))
83
+ max(1rem, env(safe-area-inset-bottom, 0px))
84
+ max(1rem, env(safe-area-inset-left, 0px));
85
+ gap: 0.5rem;
86
+ z-index: 9999;
87
+ flex-direction: column;
88
+ pointer-events: none;
89
+ box-sizing: border-box;
90
+ overflow: visible;
91
+
92
+ &[class*='top'] {
93
+ top: 0;
94
+ }
95
+
96
+ &[class*='bottom'] {
97
+ bottom: 0;
98
+ flex-direction: column-reverse;
99
+ }
100
+ }
101
+ </style>
@@ -0,0 +1,8 @@
1
+ export declare const containerClass = "toast-paper-container";
2
+ import type { ToastPosition } from './';
3
+ interface Props {
4
+ position?: ToastPosition;
5
+ }
6
+ declare const ToastContainer: import("svelte").Component<Props, {}, "">;
7
+ type ToastContainer = ReturnType<typeof ToastContainer>;
8
+ export default ToastContainer;
@@ -1,7 +1,17 @@
1
+ import type { Snippet } from 'svelte';
1
2
  import type { PaperType, PositionY } from '../../types';
2
- export declare type ToastPosition = PositionY | 'top-right' | 'bottom-right' | 'bottom-left' | 'top-left';
3
- interface ToastProps {
4
- message: string;
3
+ import type { IconNode } from '../../icons';
4
+ export type ToastPosition = PositionY | 'top-right' | 'bottom-right' | 'bottom-left' | 'top-left';
5
+ export interface ToastProps {
6
+ /** Replaces the icon chosen from `type`. */
7
+ icon?: IconNode | null;
8
+ /** Hides the icon, including the one chosen from `type`. */
9
+ hideIcon?: boolean;
10
+ /** Heading shown above the message. */
11
+ title?: string;
12
+ message?: string;
13
+ /** Custom content. Receives `close`. Replaces `message`. */
14
+ content?: Snippet<[() => void]>;
5
15
  type?: PaperType;
6
16
  duration?: number;
7
17
  position?: ToastPosition;
@@ -9,7 +19,8 @@ interface ToastProps {
9
19
  dismissible?: boolean;
10
20
  indefinite?: boolean;
11
21
  closeAriaLabel?: string;
12
- onClose?: Function;
22
+ class?: string;
23
+ onClose?: Function | null;
13
24
  }
14
25
  interface ToastMethods {
15
26
  open: (props: ToastProps | string) => void;
@@ -19,9 +30,12 @@ interface ToastMethods {
19
30
  warn: (options: OpenWithTypeParams | string) => void;
20
31
  danger: (options: OpenWithTypeParams | string) => void;
21
32
  error: (options: OpenWithTypeParams | string) => void;
33
+ clear: (position?: ToastPosition) => void;
22
34
  }
23
- declare type OpenWithTypeParams = Omit<ToastProps, 'type'>;
35
+ type OpenWithTypeParams = Omit<ToastProps, 'type'>;
24
36
  export declare function open(props: ToastProps | string): void;
37
+ /** Dismiss active toasts immediately (optionally only one position lane). */
38
+ export declare function clear(position?: ToastPosition): void;
25
39
  export declare const info: (options: OpenWithTypeParams | string) => void;
26
40
  export declare const success: (options: OpenWithTypeParams | string) => void;
27
41
  export declare const warning: (options: OpenWithTypeParams | string) => void;