@rokkit/core 1.0.0-next.34 → 1.0.0-next.35

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/core",
3
- "version": "1.0.0-next.34",
3
+ "version": "1.0.0-next.35",
4
4
  "description": "Core components, actions and stores for svelte apps.",
5
5
  "author": "Jerry Thomas <me@jerrythomas.name>",
6
6
  "license": "MIT",
@@ -24,7 +24,7 @@
24
24
  "validators": "latest",
25
25
  "vite": "^4.3.9",
26
26
  "vitest": "~0.32.3",
27
- "shared-config": "1.0.0-next.34"
27
+ "shared-config": "1.0.0-next.35"
28
28
  },
29
29
  "files": [
30
30
  "src/**/*.js",
@@ -35,8 +35,6 @@
35
35
  "exports": {
36
36
  "./src": "./src",
37
37
  "./package.json": "./package.json",
38
- "./stores": "./src/stores/index.js",
39
- "./actions": "./src/actions/index.js",
40
38
  "./constants": "./src/constants.js",
41
39
  ".": {
42
40
  "types": "./dist/index.d.ts",
@@ -44,9 +42,8 @@
44
42
  }
45
43
  },
46
44
  "dependencies": {
47
- "@rokkit/molecules": "1.0.0-next.33",
48
- "ramda": "^0.29.0",
49
- "rokkit": "1.0.0-next.33"
45
+ "date-fns": "^2.30.0",
46
+ "ramda": "^0.29.0"
50
47
  },
51
48
  "scripts": {
52
49
  "format": "prettier --write .",
@@ -0,0 +1,43 @@
1
+ import {
2
+ getDay,
3
+ getMonth,
4
+ getYear,
5
+ getDaysInMonth,
6
+ format,
7
+ isWeekend
8
+ } from 'date-fns'
9
+
10
+ export const weekdays = [
11
+ 'Sunday',
12
+ 'Monday',
13
+ 'Tuesday',
14
+ 'Wednesday',
15
+ 'Thursday',
16
+ 'Friday',
17
+ 'Saturday'
18
+ ]
19
+
20
+ export function getCalendarDays(value, holidays = [], fixed = false) {
21
+ const month = getMonth(value)
22
+ const year = getYear(value)
23
+ const offset = getDay(new Date(year, month, 1)) + 1
24
+
25
+ holidays = holidays.map((x) => format(new Date(x), 'yyyy-MMM-dd'))
26
+ let days = Array.from({ length: getDaysInMonth(value) }, (_, i) => ({
27
+ day: i + 1,
28
+ offset: i == 0 ? offset : 0,
29
+ date: new Date(year, month, i + 1)
30
+ })).map((x) => ({
31
+ ...x,
32
+ text: format(x.date, 'yyyy-MMM-dd'),
33
+ weekend: isWeekend(x.date),
34
+ holiday: holidays.includes(format(x.date, 'yyyy-MMM-dd'))
35
+ }))
36
+
37
+ if (fixed && days[0].offset > 4) {
38
+ const n = 5 * 7 - days[0].offset
39
+ days = [...days.slice(n + 1), ...days.slice(0, n + 1)]
40
+ }
41
+
42
+ return days
43
+ }
@@ -0,0 +1,12 @@
1
+ export function getLineTypes(
2
+ hasChildren = false,
3
+ parentTypes = [],
4
+ position = 'child'
5
+ ) {
6
+ let types = parentTypes.slice(0, -1).map((type) => {
7
+ return type === 'child' ? 'sibling' : type === 'last' ? 'empty' : type
8
+ })
9
+ if (parentTypes.length > 0) types.push(position)
10
+ types.push(hasChildren ? 'icon' : 'empty')
11
+ return types
12
+ }
@@ -0,0 +1,95 @@
1
+ export const defaultIcons = [
2
+ 'accordion-opened',
3
+ 'accordion-closed',
4
+ 'action-remove',
5
+ 'action-add',
6
+ 'action-clear',
7
+ 'action-search',
8
+ 'action-close',
9
+ 'action-close-filled',
10
+ 'node-opened',
11
+ 'node-closed',
12
+ 'selector-opened',
13
+ 'selector-closed',
14
+ 'checkbox-checked',
15
+ 'checkbox-unchecked',
16
+ 'checkbox-unknown',
17
+ 'rating-filled',
18
+ 'rating-empty',
19
+ 'radio-off',
20
+ 'radio-on',
21
+ 'mode-dark',
22
+ 'mode-light',
23
+ 'navigate-left',
24
+ 'navigate-right',
25
+ 'navigate-up',
26
+ 'navigate-down'
27
+ ]
28
+
29
+ export const defaultOptions = {
30
+ id: 'id',
31
+ label: 'label',
32
+ value: 'value',
33
+ checked: 'checked'
34
+ }
35
+
36
+ /**
37
+ * Structure to map custom fields for rendering
38
+ *
39
+ * @typedef FieldMapping
40
+ * @property {string} [id='id'] - Unique id for the item
41
+ * @property {string} [text='text'] - Attribute to identify the text to render
42
+ * @property {string} [url='url'] - Attribute to identify a URL
43
+ * @property {string} [icon='icon'] - Attribute to identify an icon class to render
44
+ * @property {string} [image='image'] - Attribute to identify an image to render
45
+ * @property {string} [children='children'] - Attribute to identify children of the current item
46
+ * @property {string} [summary='summary']
47
+ * @property {string} [notes='notes']
48
+ * @property {string} [props='props']
49
+ * @property {string} [isOpen='_open'] - Attribute to identify if the current item is open
50
+ * @property {string} [level='level'] - Attribute to identify level of current item
51
+ * @property {string} [parent='parent'] - Attribute to identify if the current item is a parent
52
+ * @property {string} [isDeleted='_deleted'] - Attribute to identify if the current item is deleted
53
+ * @property {FieldMapping} [fields?] - Field mapping to be used on children in the next level
54
+ */
55
+ export const defaultFields = {
56
+ id: 'id',
57
+ url: 'url',
58
+ text: 'text',
59
+ children: 'children',
60
+ icon: 'icon',
61
+ image: 'image',
62
+ component: 'component',
63
+ summary: 'summary',
64
+ notes: 'notes',
65
+ props: 'props',
66
+ target: 'target',
67
+ state: 'state',
68
+ isOpen: '_open',
69
+ isDeleted: '_deleted',
70
+ level: 'level',
71
+ parent: 'parent'
72
+ }
73
+
74
+ export const defaultKeyMap = {
75
+ ArrowRight: 'open',
76
+ ArrowLeft: 'close',
77
+ ArrowDown: 'down',
78
+ ArrowUp: 'up',
79
+ Enter: 'select',
80
+ Escape: 'deselect'
81
+ }
82
+
83
+ export function stateIconsFromNames(icons) {
84
+ return icons
85
+ .map((k) => [...k.split('-')])
86
+ .reduce(
87
+ (acc, parts) => ({
88
+ ...acc,
89
+ [parts[0]]: { ...acc[parts[0]], [parts[1]]: parts.join('-') }
90
+ }),
91
+ {}
92
+ )
93
+ }
94
+
95
+ export const defaultStateIcons = stateIconsFromNames(defaultIcons)
package/src/index.js CHANGED
@@ -1,30 +1,7 @@
1
- // export * from './constants'
2
- // export * from './items'
3
- // export * from './lib'
4
-
5
- // export { default as Icon } from './Icon.svelte'
6
- // export { default as Switch } from './Switch.svelte'
7
- // export { default as Tree } from './Tree.svelte'
8
- // export { default as Accordion } from './Accordion.svelte'
9
- // export { default as List } from './List.svelte'
10
- export { default as Searchable } from './Searchable.svelte'
11
- export { default as Scrollable } from './Scrollable.svelte'
12
- // export { default as NestedList } from './NestedList.svelte'
13
- // export { default as Tabs } from './Tabs.svelte'
14
- // export { default as BreadCrumbs } from './BreadCrumbs.svelte'
15
- export { default as NestedPaginator } from './NestedPaginator.svelte'
16
-
17
- // export { default as Alerts } from './Alerts.svelte'
18
- // export { default as Slider } from './Slider.svelte'
19
- // export { default as DropDown } from './DropDown.svelte'
20
- // export { default as DropSearch } from './DropSearch.svelte'
21
- export { default as SpinList } from './SpinList.svelte'
22
-
23
- export { default as Sidebar } from './Sidebar.svelte'
24
- export { default as SplitPane } from './SplitPane.svelte'
25
- export { default as Splitter } from './Splitter.svelte'
26
- export { default as SplitView } from './SplitView.svelte'
27
- export { default as Overlay } from './Overlay.svelte'
28
-
29
- export { default as PageNavigator } from './PageNavigator.svelte'
30
- export { default as ResponsiveGrid } from './ResponsiveGrid.svelte'
1
+ export * from './constants'
2
+ export * from './nested'
3
+ export * from './mapping'
4
+ export * from './connector'
5
+ export * from './ticks'
6
+ export * from './calendar'
7
+ export * from './utils'
package/src/mapping.js ADDED
@@ -0,0 +1,16 @@
1
+ import { defaultFields } from './constants'
2
+
3
+ export function getComponent(value, fields, using) {
4
+ return fields.component && typeof value == 'object'
5
+ ? using[value[fields.component]] ?? using.default
6
+ : using.default
7
+ }
8
+
9
+ export function getIcon(value, fields = defaultFields) {
10
+ if (fields.icon === undefined || typeof (value ?? '') !== 'object')
11
+ return null
12
+
13
+ return typeof value[fields.icon] == 'object'
14
+ ? value[fields.icon][value[fields.state]]
15
+ : value[fields.icon]
16
+ }
package/src/nested.js ADDED
@@ -0,0 +1,45 @@
1
+ import { omit } from 'ramda'
2
+ import { defaultFields } from './constants'
3
+
4
+ export function flattenNestedList(items, fields = defaultFields, level = 0) {
5
+ fields = { ...defaultFields, ...fields }
6
+ let data = []
7
+ items.map((item) => {
8
+ const children = item[fields.children] ?? []
9
+ data = [
10
+ ...data,
11
+ {
12
+ ...omit([fields.children], item),
13
+ [fields.level]: level,
14
+ [fields.parent]: children.length > 0
15
+ },
16
+ ...flattenNestedList(children, fields, level + 1)
17
+ ]
18
+ })
19
+ return data
20
+ }
21
+
22
+ /**
23
+ * Converts a path slug to a value in the menu
24
+ *
25
+ * @param {string} slug
26
+ * @returns {any}
27
+ */
28
+ export function findValueFromPath(slug, data, fields) {
29
+ fields = { ...defaultFields, ...fields }
30
+ const keys = slug.split('/')
31
+ let items = data
32
+ let value = null
33
+ keys.map((key, index) => {
34
+ const match = items.find((item) => item[fields.key] === key)
35
+ if (match) {
36
+ if (index < keys.length - 1) {
37
+ match[fields.isOpen] = true
38
+ items = match[fields.children]
39
+ } else {
40
+ value = match
41
+ }
42
+ }
43
+ })
44
+ return value
45
+ }
package/src/ticks.js ADDED
@@ -0,0 +1,16 @@
1
+ export function generateTicks(
2
+ lowerBound,
3
+ upperBound,
4
+ minorTickStep,
5
+ majorTickStep = 1
6
+ ) {
7
+ minorTickStep = minorTickStep ? minorTickStep : upperBound - lowerBound
8
+ const length = 1 + Math.ceil((upperBound - lowerBound) / minorTickStep)
9
+ const ticks = Array.from({ length }, (_, i) => ({
10
+ value: i == length - 1 ? upperBound : lowerBound + minorTickStep * i,
11
+ major: i == 0 || i == length - 1 || i % majorTickStep == 0
12
+ }))
13
+ //.map(({ value, show }) => ({ value, label: show ? value : '', major }))
14
+
15
+ return ticks
16
+ }
package/src/utils.js ADDED
@@ -0,0 +1,3 @@
1
+ export function id() {
2
+ return Math.random().toString(36).substr(2, 9)
3
+ }
@@ -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="w-full flex flex-shrink-0 flex-row cursor-pointer select-none">
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-grow flex-col"><slot /></content>
31
- </tab-view>
@@ -1,35 +0,0 @@
1
- <script>
2
- // import Icon from '../layout/Icon.svelte'
3
- import { createEventDispatcher } from 'svelte'
4
- import { defaultStateIcons } from 'rokkit/utils'
5
-
6
- const dispatch = createEventDispatcher()
7
-
8
- export let search
9
- export let searchable = true
10
- export let editable = false
11
-
12
- const actionIcons = defaultStateIcons.action
13
- </script>
14
-
15
- <toolbar class="w-full flex flex-row items-center">
16
- {#if searchable}
17
- <search class="flex flex-grow flex-row">
18
- <icon class={actionIcons.search} />
19
- <input
20
- type="search"
21
- bind:value={search}
22
- class="rounded-r-full px-3 leading-loose"
23
- placeholder="search"
24
- />
25
- </search>
26
- {/if}
27
- {#if editable}
28
- <!-- svelte-ignore a11y-click-events-have-key-events -->
29
- <icon class={actionIcons.clear} on:click={() => dispatch('clear')} />
30
- <!-- svelte-ignore a11y-click-events-have-key-events -->
31
- <icon class={actionIcons.remove} on:click={() => dispatch('remove')} />
32
- <!-- svelte-ignore a11y-click-events-have-key-events -->
33
- <icon class={actionIcons.add} on:click={() => dispatch('add')} />
34
- {/if}
35
- </toolbar>
File without changes
@@ -1,64 +0,0 @@
1
- <script>
2
- import { defaultFields, flattenNestedList } from 'rokkit/utils'
3
- import { Item, BreadCrumbs } from '@rokkit/molecules'
4
- // import { flattenNestedList } from './lib/nested'
5
- import { createEventDispatcher } from 'svelte'
6
-
7
- const dispatch = createEventDispatcher()
8
- export let items
9
- export let value
10
- export let fields
11
- export let using
12
-
13
- let trail
14
- let flatList
15
-
16
- function handleNav(event) {
17
- let current = flatList.findIndex((item) => item === value)
18
- let index = current
19
- if (event === 'previous') {
20
- while (index > 0 && !flatList[index][fields.key]) {
21
- index = index - 1
22
- }
23
- } else {
24
- while (index < flatList.length - 1 && !flatList[index][fields.key]) {
25
- index = index + 1
26
- }
27
- }
28
- if (flatList[index][fields.key]) {
29
- value = flatList[index]
30
- trail = findTrail(flatList, value)
31
- dispatch('change', { item: value, trail })
32
- }
33
- }
34
- function findTrail(items, value) {
35
- let trail = []
36
- let index = items.findIndex((item) => item === value)
37
- if (index === -1) return trail
38
-
39
- let level = items[index][fields.level]
40
- while (level > 0) {
41
- trail.unshift(items[index])
42
- index = items.findIndex(
43
- (item, i) => i < index && item[fields.level] === level - 1
44
- )
45
- level = items[index][fields.level]
46
- }
47
- return trail
48
- }
49
-
50
- $: flatList = flattenNestedList(items, fields)
51
- $: fields = { ...defaultFields, ...(fields ?? {}) }
52
- $: using = { default: Item, ...(using ?? {}) }
53
- </script>
54
-
55
- <pages>
56
- <!-- svelte-ignore a11y-click-events-have-key-events -->
57
- <icon
58
- class="arrow-left cursor-pointer"
59
- on:click={() => handleNav('previous')}
60
- />
61
- <BreadCrumbs items={trail} {fields} {using} />
62
- <!-- svelte-ignore a11y-click-events-have-key-events -->
63
- <icon class="arrow-right cursor-pointer" on:click={() => handleNav('next')} />
64
- </pages>
@@ -1,4 +0,0 @@
1
- <!-- svelte-ignore a11y-click-events-have-key-events -->
2
- <overlay class="absolute left-0 top-0 h-screen w-screen" on:click>
3
- <slot />
4
- </overlay>
@@ -1,94 +0,0 @@
1
- <script>
2
- import { createEventDispatcher } from 'svelte'
3
- import { defaultFields, defaultStateIcons } from 'rokkit/utils'
4
- import { Icon } from 'rokkit/atoms'
5
-
6
- const dispatch = createEventDispatcher()
7
-
8
- let className = ''
9
- export { className as class }
10
-
11
- export let items = []
12
- export let value = items[0]
13
- export let fields = {}
14
- export let numbers = false
15
-
16
- const navigate = defaultStateIcons.navigate
17
-
18
- let previous
19
- let next
20
-
21
- function updateOnChange(value, items) {
22
- let index = items.findIndex((x) => x == value)
23
- if (index == -1) value = items[0]
24
- // } else {
25
- previous = index > 0 ? items[index - 1] : null
26
- next = index < items.length - 1 ? items[index + 1] : null
27
- // }
28
- }
29
-
30
- function handleClick(item) {
31
- if (item) {
32
- value = item
33
- dispatch('select', value)
34
- }
35
- }
36
-
37
- $: fields = { ...defaultFields, ...fields }
38
- $: updateOnChange(value, items)
39
-
40
- // $: value = items.findIndex((x) => x == value) ? value : items[0]
41
- </script>
42
-
43
- <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
44
- <nav-pages class="grid grid-cols-3 select-none {className}" tabindex="0">
45
- <!-- svelte-ignore a11y-click-events-have-key-events -->
46
- <span
47
- class="flex cursor-pointer items-center"
48
- on:click={() => handleClick(previous)}
49
- tabIndex={previous ? 0 : -1}
50
- >
51
- {#if previous}
52
- <Icon name={navigate.left} />
53
- <p>
54
- {#if previous[fields.text]}
55
- {previous[fields.text]}
56
- {/if}
57
- </p>
58
- {/if}
59
- </span>
60
- <span class="flex items-center justify-center">
61
- <block class="flex items-center">
62
- {#each items as item, index}
63
- <!-- svelte-ignore a11y-click-events-have-key-events -->
64
- <pg
65
- class:numbers
66
- class:dot={!numbers}
67
- class:is-selected={value == item}
68
- on:click={() => handleClick(item)}
69
- tabindex="0"
70
- class="cursor-pointer"
71
- >
72
- {#if numbers}
73
- {index + 1}
74
- {/if}
75
- </pg>
76
- {/each}
77
- </block>
78
- </span>
79
- <!-- svelte-ignore a11y-click-events-have-key-events -->
80
- <span
81
- class="flex cursor-pointer items-center justify-end"
82
- on:click={() => handleClick(next)}
83
- tabIndex={next ? 0 : -1}
84
- >
85
- {#if next}
86
- <p class="text-right">
87
- {#if next[fields.text]}
88
- {next[fields.text]}
89
- {/if}
90
- </p>
91
- <Icon name={navigate.right} />
92
- {/if}
93
- </span>
94
- </nav-pages>
@@ -1,72 +0,0 @@
1
- <script>
2
- import { swipeable, navigable } from 'rokkit/actions'
3
- import { fly, fade } from 'svelte/transition'
4
- import { cubicInOut } from 'svelte/easing'
5
-
6
- let className = 'three-col'
7
- export { className as class }
8
- export let items
9
- export let small = true
10
- export let duration = 400
11
- export let easing = cubicInOut
12
- export let value
13
-
14
- let previous = -1
15
- let activeIndex = 0
16
- let direction = 1
17
- let width
18
-
19
- function handleNext() {
20
- if (activeIndex < items.length - 1) value = items[activeIndex + 1]
21
- }
22
-
23
- function handlePrevious() {
24
- if (activeIndex > 0) value = items[activeIndex - 1]
25
- }
26
-
27
- function activeIndexFromPage(value) {
28
- const index = items.findIndex((item) => item === value)
29
- return index > -1 ? index : 0
30
- }
31
-
32
- $: activeIndex = activeIndexFromPage(value)
33
- $: {
34
- direction = Math.sign(activeIndex - previous)
35
- previous = activeIndex
36
- }
37
- </script>
38
-
39
- <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
40
- <container
41
- use:swipeable={{ enabled: small }}
42
- on:swipeLeft={handleNext}
43
- on:swipeRight={handlePrevious}
44
- use:navigable={{ enabled: small }}
45
- on:previous={handlePrevious}
46
- on:next={handleNext}
47
- tabindex={0}
48
- class="overflow-hidden {className}"
49
- bind:clientWidth={width}
50
- >
51
- {#each items as item, index}
52
- {@const segmentClass = 'col-' + (index + 1)}
53
- {@const props = item.props ?? {}}
54
- {#if small && index === activeIndex}
55
- <segment
56
- class="absolute w-full h-full {segmentClass}"
57
- out:fade={{
58
- x: -1 * direction * width,
59
- duration,
60
- easing
61
- }}
62
- in:fly={{ x: direction * width, duration, easing }}
63
- >
64
- <svelte:component this={item.component} {...props} />
65
- </segment>
66
- {:else if !small}
67
- <segment class={segmentClass}>
68
- <svelte:component this={item.component} {...props} />
69
- </segment>
70
- {/if}
71
- {/each}
72
- </container>
@@ -1,8 +0,0 @@
1
- <script>
2
- let className = ''
3
- export { className as class }
4
- </script>
5
-
6
- <scroll class="flex flex-col h-full overflow-scroll {className}">
7
- <slot />
8
- </scroll>
@@ -1,19 +0,0 @@
1
- <script>
2
- import Scrollable from './Scrollable.svelte'
3
-
4
- export let search = ''
5
- </script>
6
-
7
- <div class="searchable h-full w-full flex flex-col overflow-hidden">
8
- <div class="quick-search flex flex-shrink-0 flex-grow flex-col px-4 py-2">
9
- <input
10
- type="search"
11
- bind:value={search}
12
- class="rounded-full px-3 leading-loose"
13
- placeholder="search"
14
- />
15
- </div>
16
- <Scrollable>
17
- <slot />
18
- </Scrollable>
19
- </div>
@@ -1,5 +0,0 @@
1
- <aside class="sidebar flex flex-col">
2
- <slot name="header" />
3
- <slot />
4
- <slot name="footer" />
5
- </aside>
@@ -1,48 +0,0 @@
1
- <script>
2
- import { createEventDispatcher } from 'svelte'
3
- import { defaultFields } from 'rokkit/utils'
4
- import { Item } from '@rokkit/molecules'
5
- import { navigable } from 'rokkit/actions'
6
- // import { getComponent } from './list'
7
-
8
- const dispatch = createEventDispatcher()
9
-
10
- let className = ''
11
- export { className as class }
12
- export let items = []
13
- export let fields = {}
14
- export let using = {}
15
- export let value
16
- let index = -1
17
-
18
- function moveNext() {
19
- index = index < items.length - 1 ? index + 1 : 0
20
- dispatch('select', items[index])
21
- }
22
- function moveBack() {
23
- index = index > 0 ? index - 1 : items.length - 1
24
- dispatch('select', items[index])
25
- }
26
-
27
- $: using = { default: Item, ...using }
28
- $: fields = { ...defaultFields, ...fields }
29
- $: value = index >= 0 ? items[index] : null
30
- // $: component = getComponent(value, fields)
31
- </script>
32
-
33
- <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
34
- <spin-list class="flex flex-row w-full {className}" tabindex={0}>
35
- <input
36
- type="text"
37
- class="flex flex-grow"
38
- bind:value
39
- readonly
40
- use:navigable
41
- on:next={moveNext}
42
- on:previous={moveBack}
43
- />
44
- <!-- <svelte:component this={component} bind:value={value} {fields} on:change /> -->
45
- <square class="right-0 h-full position-absolute">
46
- <icon class="i-carbon-chevron-sort" />
47
- </square>
48
- </spin-list>
@@ -1,109 +0,0 @@
1
- <script>
2
- import { createEventDispatcher } from 'svelte'
3
- import { pannable } from 'rokkit/actions'
4
-
5
- const dispatch = createEventDispatcher()
6
-
7
- export let vertical = false
8
- export let limits = [50, 30]
9
- export let pos = 70
10
- export let styles = ['', '']
11
-
12
- let refs = {}
13
-
14
- function clamp(min, max, value) {
15
- return min > value ? min : max < value ? max : value
16
- }
17
-
18
- function handlePanMove(event) {
19
- const { top, bottom, left, right } = refs.wrapper.getBoundingClientRect()
20
- const extents = horizontal ? [left, right] : [top, bottom]
21
- let px = clamp(
22
- extents[0],
23
- extents[1],
24
- horizontal ? event.detail.x : event.detail.y
25
- )
26
- pos = clamp(
27
- limits[0],
28
- 100 - limits[1],
29
- (100 * (px - extents[0])) / (extents[1] - extents[0])
30
- )
31
- dispatch('change', { pos })
32
- }
33
-
34
- $: horizontal = !vertical
35
- $: side = horizontal ? 'left' : 'top'
36
- $: dimension = horizontal ? 'width' : 'height'
37
- $: direction = vertical ? 'vertical' : 'horizontal'
38
- </script>
39
-
40
- <div class="wrapper {direction}" bind:this={refs.wrapper}>
41
- <div class={styles[0]} style="{dimension}: {pos}%;">
42
- <slot name="a" />
43
- </div>
44
- <div class={styles[1]} style="{dimension}: {100 - pos}%;">
45
- <slot name="b" />
46
- </div>
47
- <span
48
- class="wall"
49
- use:pannable
50
- on:panmove={handlePanMove}
51
- style="{side}: calc({pos}% - 8px)"
52
- />
53
- </div>
54
-
55
- <style>
56
- .wrapper {
57
- position: relative;
58
- display: flex;
59
- height: 100%;
60
- width: 100%;
61
- }
62
- .wrapper div {
63
- flex: 1 1 auto;
64
- height: 100%;
65
- }
66
-
67
- .horizontal {
68
- flex-direction: row;
69
- }
70
- .vertical {
71
- flex-direction: column;
72
- }
73
- .wall {
74
- position: absolute;
75
- z-index: 10;
76
- }
77
- .wall::after {
78
- content: '';
79
- position: absolute;
80
- background-color: var(--bg-800);
81
- }
82
- .wall:hover {
83
- cursor: ew-resize;
84
- }
85
- .horizontal .wall {
86
- padding: 0 8px;
87
- width: 0;
88
- height: 100%;
89
- cursor: ew-resize;
90
- }
91
- .horizontal .wall::after {
92
- left: 8px;
93
- top: 0;
94
- width: 1px;
95
- height: 100%;
96
- }
97
- .vertical .wall {
98
- padding: 8px 0;
99
- width: 100%;
100
- height: 0;
101
- cursor: ns-resize;
102
- }
103
- .vertical .wall::after {
104
- top: 8px;
105
- left: 0;
106
- width: 100%;
107
- height: 1px;
108
- }
109
- </style>
@@ -1,44 +0,0 @@
1
- <script>
2
- import Splitter from './Splitter.svelte'
3
-
4
- export let vertical = false
5
- export let min = 30
6
- export let max = 70
7
- export let pos = 30
8
-
9
- $: sizes = [pos, 100 - pos]
10
-
11
- $: direction = { direction: vertical ? 'flex-col' : 'flex-row' }
12
- $: sizeA = {
13
- width: vertical ? 100 : sizes[0],
14
- height: vertical ? sizes[0] : 100
15
- }
16
- $: sizeB = {
17
- width: vertical ? 100 : sizes[1],
18
- height: vertical ? sizes[1] : 100
19
- }
20
-
21
- function onSplitterChange(e) {
22
- pos = e.detail.pos - e.detail.offset
23
- }
24
- </script>
25
-
26
- <div class="relative h-full w-full flex" style:--direction={direction}>
27
- <section style:--sizeA={sizeA} class="flex flex-shrink flex-grow select-none">
28
- <slot name="a" />
29
- </section>
30
- <section style:--sizeB={sizeB} class="flex flex-shrink flex-grow select-none">
31
- <slot name="b" />
32
- </section>
33
- <Splitter {vertical} {min} {max} {pos} on:change={onSplitterChange} />
34
- </div>
35
-
36
- <style>
37
- div {
38
- flex-direction: var(--direction);
39
- }
40
- section {
41
- width: calc(var(--width) * 1%);
42
- height: calc(var(--height) * 1%);
43
- }
44
- </style>
@@ -1,95 +0,0 @@
1
- <script>
2
- // ensure that parent has position: relative.
3
- // on reaching limit remove mouse events.
4
- import { createEventDispatcher } from 'svelte'
5
- import { pannable } from 'rokkit/actions'
6
-
7
- const dispatch = createEventDispatcher()
8
-
9
- export let vertical = false
10
- export let index
11
- export let min = 0
12
- export let max = 100
13
- export let pos = 50
14
- export let offset = 0
15
-
16
- let wall
17
-
18
- function clamp(min, max, value) {
19
- return min > value ? min : max < value ? max : value
20
- }
21
-
22
- function fixLimits() {
23
- if (min > max) [min, max] = [max, min]
24
- max = clamp(0, 100, max)
25
- min = clamp(0, 100, min)
26
- pos = clamp(min, max, pos)
27
- }
28
-
29
- function handlePanMove(event) {
30
- const { top, bottom, left, right } =
31
- wall.parentElement.getBoundingClientRect()
32
- const extents = horizontal ? [left, right] : [top, bottom]
33
- let px = clamp(
34
- extents[0],
35
- extents[1],
36
- horizontal ? event.detail.x : event.detail.y
37
- )
38
-
39
- pos = clamp(min, max, (100 * (px - extents[0])) / (extents[1] - extents[0]))
40
-
41
- dispatch('change', { pos, index, offset })
42
- }
43
- $: fixLimits()
44
- $: horizontal = !vertical
45
- $: side = horizontal ? 'left' : 'top'
46
- </script>
47
-
48
- <span
49
- bind:this={wall}
50
- class="wall"
51
- class:vertical
52
- class:horizontal
53
- use:pannable
54
- on:panmove={handlePanMove}
55
- style="{side}: calc({pos}% - 8px)"
56
- />
57
-
58
- <style>
59
- .wall {
60
- position: absolute;
61
- z-index: 10;
62
- }
63
- .wall::after {
64
- content: '';
65
- position: absolute;
66
- background-color: #000;
67
- }
68
- .wall:hover {
69
- cursor: ew-resize;
70
- }
71
- .horizontal.wall {
72
- padding: 0 8px;
73
- width: 0;
74
- height: 100%;
75
- cursor: ew-resize;
76
- }
77
- .horizontal.wall::after {
78
- left: 8px;
79
- top: 0;
80
- width: 1px;
81
- height: 100%;
82
- }
83
- .vertical.wall {
84
- padding: 8px 0;
85
- width: 100%;
86
- height: 0;
87
- cursor: ns-resize;
88
- }
89
- .vertical.wall::after {
90
- top: 8px;
91
- left: 0;
92
- width: 100%;
93
- height: 1px;
94
- }
95
- </style>
@@ -1,30 +0,0 @@
1
- <script>
2
- import { createEventDispatcher } from 'svelte'
3
-
4
- const dispatch = createEventDispatcher()
5
-
6
- export let fields = {}
7
- export let using = {}
8
- export let value = null
9
- export let index = 0
10
- export let icons
11
- export let selected = false
12
- export let removable = false
13
-
14
- $: component = value[fields.component]
15
- ? using[value[fields.component]] || using.default
16
- : using.default
17
- </script>
18
-
19
- <!-- svelte-ignore a11y-click-events-have-key-events -->
20
- <tab
21
- class="flex flex-row items-center"
22
- role="option"
23
- aria-selected={selected}
24
- data-path={index}
25
- >
26
- <svelte:component this={component} {value} {fields} />
27
- {#if removable}
28
- <icon class={icons.close} on:click={() => dispatch('remove')} />
29
- {/if}
30
- </tab>
@@ -1,34 +0,0 @@
1
- <script>
2
- import { createEventDispatcher } from 'svelte'
3
- import { defaultFields } from 'rokkit/utils'
4
- import TabItem from './TabItem.svelte'
5
-
6
- const dispatch = createEventDispatcher()
7
-
8
- export let items = []
9
- export let fields = {}
10
- export let allowClose = false
11
- export let value = items[0]
12
-
13
- function activate(item) {
14
- value = item
15
- dispatch('switch', item)
16
- }
17
- function closeTab(index) {
18
- items[index].isClosed = true
19
- }
20
- $: fields = { ...defaultFields, ...fields }
21
- $: filtered = items.filter((item) => !item.isClosed)
22
- </script>
23
-
24
- {#each filtered as item, index}
25
- {@const label = item[fields.text]}
26
- <TabItem
27
- icon={item[fields.icon]}
28
- {label}
29
- {allowClose}
30
- active={value == item}
31
- on:click={() => activate(item)}
32
- on:close={() => closeTab(index)}
33
- />
34
- {/each}