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

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.36",
4
4
  "description": "Core components, actions and stores for svelte apps.",
5
5
  "author": "Jerry Thomas <me@jerrythomas.name>",
6
6
  "license": "MIT",
@@ -15,16 +15,17 @@
15
15
  "devDependencies": {
16
16
  "@sveltejs/vite-plugin-svelte": "^2.4.2",
17
17
  "@testing-library/svelte": "^4.0.3",
18
- "@vitest/coverage-c8": "^0.32.3",
19
- "@vitest/coverage-istanbul": "^0.32.3",
20
- "@vitest/ui": "~0.32.3",
18
+ "@vitest/coverage-c8": "^0.33.0",
19
+ "@vitest/coverage-istanbul": "^0.33.0",
20
+ "@vitest/coverage-v8": "^0.33.0",
21
+ "@vitest/ui": "~0.33.0",
21
22
  "jsdom": "^22.1.0",
22
- "svelte": "^4.0.1",
23
+ "svelte": "^4.0.5",
23
24
  "typescript": "^5.1.6",
24
25
  "validators": "latest",
25
- "vite": "^4.3.9",
26
- "vitest": "~0.32.3",
27
- "shared-config": "1.0.0-next.34"
26
+ "vite": "^4.4.4",
27
+ "vitest": "~0.33.0",
28
+ "shared-config": "1.0.0-next.36"
28
29
  },
29
30
  "files": [
30
31
  "src/**/*.js",
@@ -35,8 +36,6 @@
35
36
  "exports": {
36
37
  "./src": "./src",
37
38
  "./package.json": "./package.json",
38
- "./stores": "./src/stores/index.js",
39
- "./actions": "./src/actions/index.js",
40
39
  "./constants": "./src/constants.js",
41
40
  ".": {
42
41
  "types": "./dist/index.d.ts",
@@ -44,9 +43,8 @@
44
43
  }
45
44
  },
46
45
  "dependencies": {
47
- "@rokkit/molecules": "1.0.0-next.33",
48
- "ramda": "^0.29.0",
49
- "rokkit": "1.0.0-next.33"
46
+ "date-fns": "^2.30.0",
47
+ "ramda": "^0.29.0"
50
48
  },
51
49
  "scripts": {
52
50
  "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,88 @@
1
+ /**
2
+ * @type {import('./types).FieldMapping} Fields
3
+ */
4
+ export const defaultFields = {
5
+ id: 'id',
6
+ url: 'url',
7
+ text: 'text',
8
+ children: 'children',
9
+ icon: 'icon',
10
+ image: 'image',
11
+ component: 'component',
12
+ summary: 'summary',
13
+ notes: 'notes',
14
+ props: 'props',
15
+ target: 'target',
16
+ state: 'state',
17
+ isOpen: '_open',
18
+ isDeleted: '_deleted',
19
+ level: 'level',
20
+ parent: 'parent'
21
+ }
22
+
23
+ export const defaultIcons = [
24
+ 'accordion-opened',
25
+ 'accordion-closed',
26
+ 'action-remove',
27
+ 'action-add',
28
+ 'action-clear',
29
+ 'action-search',
30
+ 'action-close',
31
+ 'action-close-filled',
32
+ 'node-opened',
33
+ 'node-closed',
34
+ 'selector-opened',
35
+ 'selector-closed',
36
+ 'checkbox-checked',
37
+ 'checkbox-unchecked',
38
+ 'checkbox-unknown',
39
+ 'rating-filled',
40
+ 'rating-empty',
41
+ 'radio-off',
42
+ 'radio-on',
43
+ 'mode-dark',
44
+ 'mode-light',
45
+ 'navigate-left',
46
+ 'navigate-right',
47
+ 'navigate-up',
48
+ 'navigate-down',
49
+ 'state-error',
50
+ 'state-warning',
51
+ 'state-success',
52
+ 'state-info',
53
+ 'state-unknown',
54
+ 'validity-failed',
55
+ 'validity-warning',
56
+ 'validity-passed',
57
+ 'validity-unknown'
58
+ ]
59
+
60
+ export const defaultOptions = {
61
+ id: 'id',
62
+ label: 'label',
63
+ value: 'value',
64
+ checked: 'checked'
65
+ }
66
+
67
+ export const defaultKeyMap = {
68
+ ArrowRight: 'open',
69
+ ArrowLeft: 'close',
70
+ ArrowDown: 'down',
71
+ ArrowUp: 'up',
72
+ Enter: 'select',
73
+ Escape: 'deselect'
74
+ }
75
+
76
+ export function stateIconsFromNames(icons) {
77
+ return icons
78
+ .map((k) => [...k.split('-')])
79
+ .reduce(
80
+ (acc, parts) => ({
81
+ ...acc,
82
+ [parts[0]]: { ...acc[parts[0]], [parts[1]]: parts.join('-') }
83
+ }),
84
+ {}
85
+ )
86
+ }
87
+
88
+ export const defaultStateIcons = stateIconsFromNames(defaultIcons)
package/src/index.js CHANGED
@@ -1,30 +1,8 @@
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
+ import './types'
2
+ export * from './constants'
3
+ export * from './nested'
4
+ export * from './mapping'
5
+ export * from './connector'
6
+ export * from './ticks'
7
+ export * from './calendar'
8
+ export * from './utils'
package/src/mapping.js ADDED
@@ -0,0 +1,36 @@
1
+ import { defaultFields } from './constants'
2
+
3
+ /**
4
+ * Get the component to be used to render the item.
5
+ * If the component is null or undefined, it will return the default component.
6
+ *
7
+ * @param {object|string} value
8
+ * @param {import('./types.js').FieldMapping} fields
9
+ * @param {import('./types.js').ComponentMap} using
10
+ */
11
+ export function getComponent(value, fields, using) {
12
+ return fields.component && typeof value == 'object'
13
+ ? using[value[fields.component]] ?? using.default
14
+ : using.default
15
+ }
16
+
17
+ /**
18
+ * Get the icon for the item. If the icon is an object, it will use the state to determine which icon to use.
19
+ *
20
+ * @param {object|string} value
21
+ * @param {import('./types.js').FieldMapping} fields
22
+ */
23
+ export function getIcon(value, fields = defaultFields) {
24
+ if (fields.icon === undefined || typeof (value ?? '') !== 'object')
25
+ return null
26
+
27
+ return typeof value[fields.icon] == 'object'
28
+ ? value[fields.icon][value[fields.state]]
29
+ : value[fields.icon]
30
+ }
31
+
32
+ export function getId(node, fields = defaultFields) {
33
+ return typeof node === 'object' && node !== null
34
+ ? node[fields.id] ?? node[fields.text]
35
+ : node
36
+ }
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/types.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Structure to map custom fields for rendering. This is used to identofy the attributes for various purposes.
3
+ *
4
+ * @typedef FieldMapping
5
+ * @property {string} [id='id'] Unique id for the item
6
+ * @property {string} [text='text'] the text to render
7
+ * @property {string} [url='url'] a URL
8
+ * @property {string} [icon='icon'] icon to render
9
+ * @property {string} [image='image'] the image to render
10
+ * @property {string} [children='children'] children of the item
11
+ * @property {string} [summary='summary']
12
+ * @property {string} [notes='notes']
13
+ * @property {string} [props='props']
14
+ * @property {string} [isOpen='_open'] item is open or closed
15
+ * @property {string} [level='level'] level of item
16
+ * @property {string} [parent='parent'] item is a parent
17
+ * @property {string} [isDeleted='_deleted'] item is deleted
18
+ * @property {FieldMapping} [fields] Field mapping to be used on children in the next level
19
+ */
20
+
21
+ /**
22
+ * Component map to be used to render the item.
23
+ * @typedef {Object<string, import('svelte').SvelteComponent>} ComponentMap
24
+ */
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}