@rokkit/core 1.0.0-next.13 → 1.0.0-next.130
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.
- package/dist/calendar.d.ts +10 -0
- package/dist/colors/index.d.ts +47 -0
- package/dist/connector.d.ts +8 -0
- package/dist/constants.d.ts +88 -0
- package/dist/events.d.ts +12 -0
- package/dist/field-mapper.d.ts +60 -0
- package/dist/index.d.ts +13 -0
- package/dist/key-event-map.d.ts +18 -0
- package/dist/mapped-items.d.ts +14 -0
- package/dist/mapping.d.ts +14 -0
- package/dist/nested.d.ts +9 -0
- package/dist/string.d.ts +59 -0
- package/dist/theme.d.ts +96 -0
- package/dist/ticks.d.ts +10 -0
- package/dist/types.d.ts +300 -0
- package/dist/utils.d.ts +107 -0
- package/dist/vite/icon-collections.d.ts +32 -0
- package/dist/vite/index.d.ts +1 -0
- package/package.json +24 -39
- package/src/calendar.js +44 -0
- package/src/colors/extra.json +16 -0
- package/src/colors/syntax.json +42 -0
- package/src/colors/tailwind.json +275 -0
- package/src/connector.js +34 -0
- package/src/constants.js +181 -107
- package/src/events.js +32 -0
- package/src/field-mapper.js +147 -0
- package/src/index.js +19 -27
- package/src/key-event-map.js +36 -0
- package/src/mapped-items.js +22 -0
- package/src/mapping.js +21 -0
- package/src/nested.js +28 -0
- package/src/string.js +97 -0
- package/src/ticks.js +26 -0
- package/src/types.js +160 -0
- package/src/utils.js +250 -0
- package/src/vite/icon-collections.js +73 -0
- package/src/vite/index.js +1 -0
- package/LICENSE +0 -21
- package/README.md +0 -1
- package/src/Accordion.svelte +0 -80
- package/src/Alerts.svelte +0 -39
- package/src/DropDown.svelte +0 -82
- package/src/DropSearch.svelte +0 -67
- package/src/EditableTabs.svelte +0 -31
- package/src/Icon.svelte +0 -15
- package/src/List-Discard.svelte +0 -48
- package/src/List.svelte +0 -65
- package/src/ListActions.svelte +0 -35
- package/src/NavTabs.svelte +0 -0
- package/src/NestedList.svelte +0 -77
- package/src/Overlay.svelte +0 -4
- package/src/PageNavigator.svelte +0 -94
- package/src/ResponsiveGrid.svelte +0 -73
- package/src/Scrollable.svelte +0 -8
- package/src/Searchable.svelte +0 -19
- package/src/Sidebar.svelte +0 -5
- package/src/Slider.svelte +0 -17
- package/src/SpinList.svelte +0 -48
- package/src/SplitPane.svelte +0 -109
- package/src/SplitView.svelte +0 -44
- package/src/Splitter.svelte +0 -95
- package/src/TabItem.svelte +0 -27
- package/src/TabItems.svelte +0 -34
- package/src/Tabs.svelte +0 -49
- package/src/Tree.svelte +0 -45
- package/src/actions/dismissable.js +0 -24
- package/src/actions/fillable.js +0 -114
- package/src/actions/hierarchy.js +0 -189
- package/src/actions/index.js +0 -7
- package/src/actions/navigable.js +0 -43
- package/src/actions/navigator.js +0 -179
- package/src/actions/pannable.js +0 -50
- package/src/actions/swipeable.js +0 -56
- package/src/actions/themeable.js +0 -23
- package/src/items/Collapsible.svelte +0 -51
- package/src/items/Connector.svelte +0 -26
- package/src/items/Link.svelte +0 -18
- package/src/items/Node.svelte +0 -52
- package/src/items/Pill.svelte +0 -19
- package/src/items/Separator.svelte +0 -1
- package/src/items/Summary.svelte +0 -27
- package/src/items/Text.svelte +0 -21
- package/src/items/index.js +0 -8
- package/src/list.js +0 -14
- package/src/mocks/Custom.svelte +0 -7
- package/src/mocks/index.js +0 -10
- package/src/stores/alerts.js +0 -3
- package/src/stores/index.js +0 -6
- package/src/stores/persist.js +0 -63
- package/src/stores/theme.js +0 -34
package/src/utils.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { has, isNil } from 'ramda'
|
|
2
|
+
import { DATA_IMAGE_REGEX, ITEM_SNIPPET } from './constants'
|
|
3
|
+
|
|
4
|
+
let idCounter = 0
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* RTL language codes (ISO 639-1)
|
|
8
|
+
* @type {string[]}
|
|
9
|
+
*/
|
|
10
|
+
const RTL_LANGUAGES = [
|
|
11
|
+
'ar', // Arabic
|
|
12
|
+
'he', // Hebrew
|
|
13
|
+
'fa', // Persian/Farsi
|
|
14
|
+
'ur', // Urdu
|
|
15
|
+
'yi', // Yiddish
|
|
16
|
+
'ps', // Pashto
|
|
17
|
+
'sd', // Sindhi
|
|
18
|
+
'ug', // Uyghur
|
|
19
|
+
'ku', // Kurdish (Sorani)
|
|
20
|
+
'dv' // Divehi/Maldivian
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Detects text direction based on HTML lang attribute
|
|
25
|
+
* @returns {'ltr' | 'rtl'}
|
|
26
|
+
*/
|
|
27
|
+
export function detectDirection() {
|
|
28
|
+
if (typeof document === 'undefined') return 'ltr'
|
|
29
|
+
|
|
30
|
+
// Check dir attribute first (explicit override)
|
|
31
|
+
const htmlDir = document.documentElement.getAttribute('dir')
|
|
32
|
+
if (htmlDir === 'rtl' || htmlDir === 'ltr') return htmlDir
|
|
33
|
+
|
|
34
|
+
// Detect from lang attribute
|
|
35
|
+
const lang = document.documentElement.getAttribute('lang')
|
|
36
|
+
if (lang) {
|
|
37
|
+
// Extract primary language code (e.g., 'ar-SA' -> 'ar')
|
|
38
|
+
const primaryLang = lang.split('-')[0].toLowerCase()
|
|
39
|
+
if (RTL_LANGUAGES.includes(primaryLang)) return 'rtl'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return 'ltr'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Checks if current document direction is RTL
|
|
47
|
+
* @returns {boolean}
|
|
48
|
+
*/
|
|
49
|
+
export function isRTL() {
|
|
50
|
+
return detectDirection() === 'rtl'
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Finds the closest ancestor of the given element that has the given attribute.
|
|
54
|
+
*
|
|
55
|
+
* @param {HTMLElement} element
|
|
56
|
+
* @param {string} attribute
|
|
57
|
+
* @returns {HTMLElement|null}
|
|
58
|
+
*/
|
|
59
|
+
export function getClosestAncestorWithAttribute(element, attribute) {
|
|
60
|
+
if (!element) return null
|
|
61
|
+
if (element.getAttribute(attribute)) return element
|
|
62
|
+
return getClosestAncestorWithAttribute(element.parentElement, attribute)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* A function that performs no operations.
|
|
67
|
+
*/
|
|
68
|
+
export function noop() {
|
|
69
|
+
// intentionally empty to support default actions
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Generates a random id
|
|
74
|
+
*
|
|
75
|
+
* @returns {string} A random id
|
|
76
|
+
*/
|
|
77
|
+
export function id(prefix = '') {
|
|
78
|
+
return [prefix, Math.random().toString(36).substring(2, 9), ++idCounter]
|
|
79
|
+
.filter((x) => !isNil(x) && x !== '')
|
|
80
|
+
.join('-')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if a value is a json object
|
|
85
|
+
*
|
|
86
|
+
* @param {*} val
|
|
87
|
+
* @returns {boolean}
|
|
88
|
+
*/
|
|
89
|
+
export function isObject(val) {
|
|
90
|
+
return typeof val === 'object' && !isNil(val) && !(val instanceof Date)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Converts the value to a string. If the value is an object, it will convert it to a JSON string.
|
|
95
|
+
*
|
|
96
|
+
* @param {*} value
|
|
97
|
+
* @returns {string}
|
|
98
|
+
*/
|
|
99
|
+
export function toString(value) {
|
|
100
|
+
if (value === null || value === undefined) return value
|
|
101
|
+
if (isObject(value)) return JSON.stringify(value, null, 2)
|
|
102
|
+
return value.toString()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Generates icon shortcuts for a collection of icons
|
|
107
|
+
*
|
|
108
|
+
* @param {string[]} icons
|
|
109
|
+
* @param {string} collection
|
|
110
|
+
* @param {string} variants
|
|
111
|
+
* @returns {Object}
|
|
112
|
+
*/
|
|
113
|
+
export function iconShortcuts(icons, collection, variants) {
|
|
114
|
+
const suffix = variants ? `-${variants}` : ''
|
|
115
|
+
const shortcuts = !collection
|
|
116
|
+
? {}
|
|
117
|
+
: icons.reduce(
|
|
118
|
+
(acc, name) => ({
|
|
119
|
+
...acc,
|
|
120
|
+
[name]: [collection, name].join(':') + suffix
|
|
121
|
+
}),
|
|
122
|
+
{}
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return shortcuts
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Scales the path by the size
|
|
130
|
+
*
|
|
131
|
+
* @param {number} size
|
|
132
|
+
* @param {string|number} x
|
|
133
|
+
* @returns {string|number}
|
|
134
|
+
*/
|
|
135
|
+
export function scaledPath(size, x) {
|
|
136
|
+
if (Array.isArray(x)) return x.map((v) => scaledPath(size, v)).join(' ')
|
|
137
|
+
return typeof x === 'number' ? x * size : x
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Gets a key string from path
|
|
142
|
+
* @param {string[]} path
|
|
143
|
+
* @returns {string}
|
|
144
|
+
*/
|
|
145
|
+
export function getKeyFromPath(path) {
|
|
146
|
+
return Array.isArray(path) ? path.join('-') : [path].join('-')
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Gets a path array from key string
|
|
151
|
+
* @param {string} key
|
|
152
|
+
* @returns {string[]}
|
|
153
|
+
*/
|
|
154
|
+
export function getPathFromKey(key) {
|
|
155
|
+
return key.split('-').map(Number)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get snippet function from an object
|
|
160
|
+
* @param {Object} obj
|
|
161
|
+
* @param {string} key
|
|
162
|
+
* @param {null|Function} defaultSnippet
|
|
163
|
+
* @returns {Function|undefined}
|
|
164
|
+
*/
|
|
165
|
+
export function getSnippet(obj, key, defaultSnippet = null) {
|
|
166
|
+
if (has(key, obj) && typeof obj[key] === 'function') {
|
|
167
|
+
return obj[key]
|
|
168
|
+
}
|
|
169
|
+
return defaultSnippet
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Resolve which snippet to render for a proxy item.
|
|
174
|
+
*
|
|
175
|
+
* Checks proxy.snippet for a per-item named override first (e.g. item.snippet = 'highlighted').
|
|
176
|
+
* Falls back to the component-level fallback snippet name (e.g. 'itemContent' / 'groupContent').
|
|
177
|
+
* Returns null if neither is found.
|
|
178
|
+
*
|
|
179
|
+
* @param {Record<string, unknown>} snippets - snippets passed to the component
|
|
180
|
+
* @param {{ snippet?: string | null }} proxy - any object with an optional .snippet property
|
|
181
|
+
* @param {string} [fallback] - fallback snippet name; defaults to ITEM_SNIPPET ('itemContent')
|
|
182
|
+
* @returns {Function | null}
|
|
183
|
+
*/
|
|
184
|
+
export function resolveSnippet(snippets, proxy, fallback = ITEM_SNIPPET) {
|
|
185
|
+
const name = proxy?.snippet
|
|
186
|
+
if (name && typeof snippets[name] === 'function') return snippets[name]
|
|
187
|
+
const fb = snippets[fallback]
|
|
188
|
+
return typeof fb === 'function' ? fb : null
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* convert hex string to `{r} {g} {b}`
|
|
193
|
+
* @param {string} hex
|
|
194
|
+
* @return {string}
|
|
195
|
+
*/
|
|
196
|
+
export function hex2rgb(hex) {
|
|
197
|
+
const [r, g, b] = hex.match(/\w\w/g).map((x) => parseInt(x, 16))
|
|
198
|
+
return `${r},${g},${b}`
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Checks if a string is a valid image URL
|
|
203
|
+
*
|
|
204
|
+
* @param {string} str - The string to check
|
|
205
|
+
* @returns {boolean} - Returns true if the string is an image URL
|
|
206
|
+
*/
|
|
207
|
+
function isImageUrl(str) {
|
|
208
|
+
// Fallback regex-based validation
|
|
209
|
+
const fallbackValidation = () => {
|
|
210
|
+
const urlRegex = /^https?:\/\/.+\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff)(\?.*)?$/i
|
|
211
|
+
return urlRegex.test(str)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Check if the string looks like a URL
|
|
215
|
+
try {
|
|
216
|
+
// Use browser-native URL constructor if available
|
|
217
|
+
if (typeof URL !== 'undefined') {
|
|
218
|
+
const url = new URL(str)
|
|
219
|
+
// Only accept HTTP/HTTPS protocols
|
|
220
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
221
|
+
return false
|
|
222
|
+
}
|
|
223
|
+
// Check common image extensions
|
|
224
|
+
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.tiff']
|
|
225
|
+
const path = url.pathname.toLowerCase()
|
|
226
|
+
return imageExtensions.some((ext) => path.endsWith(ext))
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Fallback if URL constructor is not available
|
|
230
|
+
return fallbackValidation()
|
|
231
|
+
|
|
232
|
+
} catch {
|
|
233
|
+
// Fallback if URL constructor fails
|
|
234
|
+
return fallbackValidation()
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* A utility function that detects if a string is an image URL or image data (base64)
|
|
239
|
+
*
|
|
240
|
+
* @param {string} str - The string to check
|
|
241
|
+
* @returns {string|null} - Returns the original string if it's an image URL or image data, otherwise null
|
|
242
|
+
*/
|
|
243
|
+
export function getImage(str) {
|
|
244
|
+
if (DATA_IMAGE_REGEX.test(str)) return str
|
|
245
|
+
// Check if it's a URL
|
|
246
|
+
|
|
247
|
+
if (isImageUrl(str)) return str
|
|
248
|
+
|
|
249
|
+
return null
|
|
250
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createRequire } from 'module'
|
|
2
|
+
import { resolve, isAbsolute } from 'path'
|
|
3
|
+
import { readFileSync } from 'fs'
|
|
4
|
+
|
|
5
|
+
// Two require contexts: CWD (for site-specific packages like @iconify-json/*)
|
|
6
|
+
// and the module's own location (for workspace packages like @rokkit/icons).
|
|
7
|
+
const requireFromCwd = createRequire(resolve(process.cwd(), 'package.json'))
|
|
8
|
+
const requireFromModule = createRequire(import.meta.url)
|
|
9
|
+
|
|
10
|
+
function requirePackage(jsonPath) {
|
|
11
|
+
try {
|
|
12
|
+
return requireFromCwd(jsonPath)
|
|
13
|
+
} catch {
|
|
14
|
+
return requireFromModule(jsonPath)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates icon collection loaders for UnoCSS presetIcons from a simple config.
|
|
20
|
+
*
|
|
21
|
+
* This function transforms a map of collection names to JSON package paths
|
|
22
|
+
* into the format expected by UnoCSS's presetIcons.
|
|
23
|
+
*
|
|
24
|
+
* Supports three types of paths:
|
|
25
|
+
* - Package paths (e.g., '@rokkit/icons/ui.json') - resolved via require
|
|
26
|
+
* - Absolute paths (e.g., '/path/to/icons.json') - used directly
|
|
27
|
+
* - Relative paths (e.g., './static/icons.json') - resolved from process.cwd()
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // uno.config.js
|
|
31
|
+
* import { iconCollections } from '@rokkit/core/vite'
|
|
32
|
+
*
|
|
33
|
+
* export default defineConfig({
|
|
34
|
+
* presets: [
|
|
35
|
+
* presetIcons({
|
|
36
|
+
* collections: iconCollections({
|
|
37
|
+
* rokkit: '@rokkit/icons/ui.json',
|
|
38
|
+
* logo: '@rokkit/icons/auth.json',
|
|
39
|
+
* solar: '@iconify-json/solar/icons.json',
|
|
40
|
+
* custom: './static/icons/custom.json'
|
|
41
|
+
* })
|
|
42
|
+
* })
|
|
43
|
+
* ]
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* @param {Record<string, string>} config - Map of collection alias to JSON path
|
|
47
|
+
* @returns {Record<string, () => any>} Collections object for presetIcons
|
|
48
|
+
*/
|
|
49
|
+
export function iconCollections(config) {
|
|
50
|
+
if (!config || typeof config !== 'object') {
|
|
51
|
+
return {}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return Object.entries(config).reduce((acc, [alias, jsonPath]) => {
|
|
55
|
+
acc[alias] = () => {
|
|
56
|
+
// Check if it's a relative path (starts with ./ or ../)
|
|
57
|
+
if (jsonPath.startsWith('./') || jsonPath.startsWith('../')) {
|
|
58
|
+
// Resolve relative to current working directory (where the config is)
|
|
59
|
+
const absolutePath = resolve(process.cwd(), jsonPath)
|
|
60
|
+
return JSON.parse(readFileSync(absolutePath, 'utf-8'))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check if it's an absolute path
|
|
64
|
+
if (isAbsolute(jsonPath)) {
|
|
65
|
+
return JSON.parse(readFileSync(jsonPath, 'utf-8'))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Otherwise treat as a package path; try CWD first (site packages), then module location
|
|
69
|
+
return requirePackage(jsonPath)
|
|
70
|
+
}
|
|
71
|
+
return acc
|
|
72
|
+
}, {})
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { iconCollections } from './icon-collections.js'
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2022 Jerry Thomas
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Core Components
|
package/src/Accordion.svelte
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { createEventDispatcher } from 'svelte'
|
|
3
|
-
import { defaultFields } from './constants'
|
|
4
|
-
import { Text, Summary } from './items'
|
|
5
|
-
import List from './List.svelte'
|
|
6
|
-
import { navigator } from './actions/navigator'
|
|
7
|
-
|
|
8
|
-
const dispatch = createEventDispatcher()
|
|
9
|
-
let className = ''
|
|
10
|
-
export { className as class }
|
|
11
|
-
export let items = []
|
|
12
|
-
export let fields = {}
|
|
13
|
-
export let using = {}
|
|
14
|
-
export let autoClose = false
|
|
15
|
-
export let value = null
|
|
16
|
-
let cursor = []
|
|
17
|
-
|
|
18
|
-
$: fields = { ...defaultFields, ...fields }
|
|
19
|
-
$: using = { default: Text, ...using }
|
|
20
|
-
|
|
21
|
-
function handle(event) {
|
|
22
|
-
// console.log(event.type, event.detail)
|
|
23
|
-
value = event.detail.node
|
|
24
|
-
cursor = event.detail.path
|
|
25
|
-
if (['collapse', 'expand'].includes(event.type)) {
|
|
26
|
-
if (autoClose) {
|
|
27
|
-
items.map((x) => {
|
|
28
|
-
if (x !== value && x[fields.isOpen]) {
|
|
29
|
-
x[fields.isOpen] = false
|
|
30
|
-
}
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
items = items
|
|
34
|
-
}
|
|
35
|
-
dispatch(event.type, event.detail)
|
|
36
|
-
}
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
40
|
-
<accordion
|
|
41
|
-
class="flex flex-col w-full select-none {className}"
|
|
42
|
-
tabindex="0"
|
|
43
|
-
use:navigator={{
|
|
44
|
-
items,
|
|
45
|
-
fields,
|
|
46
|
-
enabled: true,
|
|
47
|
-
indices: cursor
|
|
48
|
-
}}
|
|
49
|
-
on:select={handle}
|
|
50
|
-
on:move={handle}
|
|
51
|
-
on:expand={handle}
|
|
52
|
-
on:collapse={handle}
|
|
53
|
-
>
|
|
54
|
-
{#each items as item, index}
|
|
55
|
-
{@const hasItems =
|
|
56
|
-
item[fields.children] && item[fields.children].length > 0}
|
|
57
|
-
{@const itemFields = { ...fields, ...(fields.fields ?? fields) }}
|
|
58
|
-
|
|
59
|
-
<div
|
|
60
|
-
id={'id-' + index}
|
|
61
|
-
class="flex flex-col"
|
|
62
|
-
class:is-expanded={item[fields.isOpen]}
|
|
63
|
-
class:is-selected={item === value}
|
|
64
|
-
data-path={index}
|
|
65
|
-
>
|
|
66
|
-
<Summary {fields} {using} bind:content={item} />
|
|
67
|
-
{#if hasItems && item[fields.isOpen]}
|
|
68
|
-
<List
|
|
69
|
-
bind:items={item[fields.children]}
|
|
70
|
-
bind:value
|
|
71
|
-
fields={itemFields}
|
|
72
|
-
{using}
|
|
73
|
-
on:select
|
|
74
|
-
hierarchy={[index]}
|
|
75
|
-
tabindex="-1"
|
|
76
|
-
/>
|
|
77
|
-
{/if}
|
|
78
|
-
</div>
|
|
79
|
-
{/each}
|
|
80
|
-
</accordion>
|
package/src/Alerts.svelte
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { fade } from 'svelte/transition'
|
|
3
|
-
import { flip } from 'svelte/animate'
|
|
4
|
-
import { alerts } from './stores'
|
|
5
|
-
import { dismissable } from './actions'
|
|
6
|
-
|
|
7
|
-
function dismissAll() {
|
|
8
|
-
unreadAlerts.map((alert) => (alert.dismissed = true))
|
|
9
|
-
alerts.set([...$alerts])
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function dismiss(alert) {
|
|
13
|
-
alert.dismissed = true
|
|
14
|
-
alerts.set([...$alerts])
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
$: unreadAlerts = $alerts.filter((x) => x.dismissed)
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
{#if unreadAlerts.length > 0}
|
|
21
|
-
<alert-list
|
|
22
|
-
class="flex flex-col gap-2 absolute z-10"
|
|
23
|
-
use:dismissable
|
|
24
|
-
on:dismiss={dismissAll}
|
|
25
|
-
>
|
|
26
|
-
{#each unreadAlerts as alert (alert.id)}
|
|
27
|
-
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
28
|
-
<alert
|
|
29
|
-
class={alert.type}
|
|
30
|
-
on:click|stopPropagation={dismiss(alert)}
|
|
31
|
-
animate:flip
|
|
32
|
-
in:fade
|
|
33
|
-
out:fade
|
|
34
|
-
>
|
|
35
|
-
{alert.message}
|
|
36
|
-
</alert>
|
|
37
|
-
{/each}
|
|
38
|
-
</alert-list>
|
|
39
|
-
{/if}
|
package/src/DropDown.svelte
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { createEventDispatcher } from 'svelte'
|
|
3
|
-
import { dismissable } from './actions'
|
|
4
|
-
import { defaultFields, defaultStateIcons } from './constants.js'
|
|
5
|
-
|
|
6
|
-
import Icon from './Icon.svelte'
|
|
7
|
-
import Text from './items/Text.svelte'
|
|
8
|
-
import List from './List.svelte'
|
|
9
|
-
import Slider from './Slider.svelte'
|
|
10
|
-
|
|
11
|
-
const dispatch = createEventDispatcher()
|
|
12
|
-
|
|
13
|
-
let className = ''
|
|
14
|
-
export { className as class }
|
|
15
|
-
export let items = []
|
|
16
|
-
export let fields = defaultFields
|
|
17
|
-
export let using = { default: Text }
|
|
18
|
-
export let value = null
|
|
19
|
-
export let title
|
|
20
|
-
export let icon
|
|
21
|
-
export let small = false
|
|
22
|
-
|
|
23
|
-
$: using = { default: Text, ...using }
|
|
24
|
-
$: fields = { ...defaultFields, ...fields }
|
|
25
|
-
|
|
26
|
-
let offsetTop = 0
|
|
27
|
-
let open = false
|
|
28
|
-
let icons = defaultStateIcons.selector
|
|
29
|
-
|
|
30
|
-
function handleSelect(event) {
|
|
31
|
-
open = false
|
|
32
|
-
dispatch('change', event.detail)
|
|
33
|
-
}
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
37
|
-
<drop-down
|
|
38
|
-
class="flex w-full relative cursor-pointer select-none dropdown {className}"
|
|
39
|
-
class:open
|
|
40
|
-
tabindex="0"
|
|
41
|
-
aria-haspopup="true"
|
|
42
|
-
aria-controls="menu"
|
|
43
|
-
use:dismissable
|
|
44
|
-
on:blur={() => (open = false)}
|
|
45
|
-
on:dismiss={() => (open = false)}
|
|
46
|
-
>
|
|
47
|
-
<button
|
|
48
|
-
on:click|stopPropagation={() => (open = !open)}
|
|
49
|
-
class="flex"
|
|
50
|
-
bind:clientHeight={offsetTop}
|
|
51
|
-
tabindex="-1"
|
|
52
|
-
>
|
|
53
|
-
{#if icon}
|
|
54
|
-
<Icon name={icon} />
|
|
55
|
-
{/if}
|
|
56
|
-
{#if !small && title}
|
|
57
|
-
<p>{title}</p>
|
|
58
|
-
{/if}
|
|
59
|
-
{#if open}
|
|
60
|
-
<icon class={icons.opened} />
|
|
61
|
-
{:else}
|
|
62
|
-
<icon class={icons.closed} />
|
|
63
|
-
{/if}
|
|
64
|
-
</button>
|
|
65
|
-
{#if open}
|
|
66
|
-
<!-- <div
|
|
67
|
-
class="flex flex-col absolute z-10 h-fit w-full menu"
|
|
68
|
-
style:top="{offsetTop}px"
|
|
69
|
-
> -->
|
|
70
|
-
<Slider top={offsetTop}>
|
|
71
|
-
<List
|
|
72
|
-
{items}
|
|
73
|
-
{fields}
|
|
74
|
-
{using}
|
|
75
|
-
bind:value
|
|
76
|
-
on:select={handleSelect}
|
|
77
|
-
tabindex="-1"
|
|
78
|
-
/>
|
|
79
|
-
</Slider>
|
|
80
|
-
<!-- </div> -->
|
|
81
|
-
{/if}
|
|
82
|
-
</drop-down>
|
package/src/DropSearch.svelte
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { defaultFields } from './constants.js'
|
|
3
|
-
import List from './List.svelte'
|
|
4
|
-
import Slider from './Slider.svelte'
|
|
5
|
-
import { Text } from './items'
|
|
6
|
-
|
|
7
|
-
export let data
|
|
8
|
-
export let value = null
|
|
9
|
-
export let fields = defaultFields
|
|
10
|
-
export let using = { default: Text }
|
|
11
|
-
|
|
12
|
-
$: using = { default: Text, ...using }
|
|
13
|
-
$: fields = { ...defaultFields, ...fields }
|
|
14
|
-
|
|
15
|
-
let opened = false
|
|
16
|
-
let search
|
|
17
|
-
let searchBox
|
|
18
|
-
|
|
19
|
-
// on search change filter list
|
|
20
|
-
function handleSelect(event) {
|
|
21
|
-
console.log('selected', event)
|
|
22
|
-
value = event.detail
|
|
23
|
-
search = event.detail[fields.text]
|
|
24
|
-
}
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
28
|
-
<div
|
|
29
|
-
class="flex flex-col outline-none w-full h-12 relative dropdown"
|
|
30
|
-
tabindex={0}
|
|
31
|
-
>
|
|
32
|
-
<div class="flex flex-shrink-0 h-12 items-center pl-4 selected-item">
|
|
33
|
-
<span class="flex flex-grow">
|
|
34
|
-
<input
|
|
35
|
-
type="text"
|
|
36
|
-
class="p-0 border-none bg-transparent w-full"
|
|
37
|
-
bind:value={search}
|
|
38
|
-
bind:this={searchBox}
|
|
39
|
-
on:focus={() => {
|
|
40
|
-
opened = true
|
|
41
|
-
searchBox.select()
|
|
42
|
-
}}
|
|
43
|
-
on:blur={() => {
|
|
44
|
-
opened = false
|
|
45
|
-
}}
|
|
46
|
-
/>
|
|
47
|
-
</span>
|
|
48
|
-
{#if opened}
|
|
49
|
-
<icon class="selector-opened" />
|
|
50
|
-
{:else}
|
|
51
|
-
<icon class="selector-closed" />
|
|
52
|
-
{/if}
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
{#if opened}
|
|
56
|
-
<Slider>
|
|
57
|
-
<List
|
|
58
|
-
bind:items={data}
|
|
59
|
-
bind:value
|
|
60
|
-
{fields}
|
|
61
|
-
{using}
|
|
62
|
-
on:select={handleSelect}
|
|
63
|
-
on:change
|
|
64
|
-
/>
|
|
65
|
-
</Slider>
|
|
66
|
-
{/if}
|
|
67
|
-
</div>
|
package/src/EditableTabs.svelte
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import TabItems from './TabItems.svelte'
|
|
3
|
-
import TabItem from './TabItem.svelte'
|
|
4
|
-
|
|
5
|
-
let className = ''
|
|
6
|
-
export { className as class }
|
|
7
|
-
export let items = []
|
|
8
|
-
export let fields = {}
|
|
9
|
-
export let title = null
|
|
10
|
-
export let allowAdd = false
|
|
11
|
-
export let allowClose = false
|
|
12
|
-
export let value = items[0]
|
|
13
|
-
|
|
14
|
-
function addTab() {
|
|
15
|
-
items = [...items, {}]
|
|
16
|
-
value = items[items.length - 1]
|
|
17
|
-
}
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<tab-view class="flex flex-col w-full flex-grow {className}">
|
|
21
|
-
<tabs class="flex flex-row flex-shrink-0 w-full select-none cursor-pointer">
|
|
22
|
-
{#if title}
|
|
23
|
-
<p>{title}</p>
|
|
24
|
-
{/if}
|
|
25
|
-
<TabItems {items} {fields} {allowClose} bind:value on:close />
|
|
26
|
-
{#if allowAdd}
|
|
27
|
-
<TabItem label="+" on:click={addTab} />
|
|
28
|
-
{/if}
|
|
29
|
-
</tabs>
|
|
30
|
-
<content class="flex flex-col flex-grow"><slot /></content>
|
|
31
|
-
</tab-view>
|
package/src/Icon.svelte
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
let className = ''
|
|
3
|
-
export { className as class }
|
|
4
|
-
|
|
5
|
-
export let name = ''
|
|
6
|
-
let h
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
|
-
<square-icon
|
|
10
|
-
class="flex flex-col flex-shrink-0 h-full items-center justify-center {className}"
|
|
11
|
-
bind:clientHeight={h}
|
|
12
|
-
style:width="{h}px"
|
|
13
|
-
>
|
|
14
|
-
<icon class={name} aria-hidden="true" />
|
|
15
|
-
</square-icon>
|