@inkbar/svelte 0.8.0 → 0.10.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.
- package/README.md +71 -6
- package/dist/components/InkDownloadButton.svelte +62 -0
- package/dist/components/InkDownloadButton.svelte.d.ts +14 -0
- package/dist/components/InkDownloadButton.svelte.d.ts.map +1 -0
- package/dist/components/InkFindBar.svelte +18 -15
- package/dist/components/InkFindBar.svelte.d.ts.map +1 -1
- package/dist/components/InkHighlightMenu.svelte +101 -93
- package/dist/components/InkHighlightMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkPanel.svelte +73 -0
- package/dist/components/InkPanel.svelte.d.ts +18 -0
- package/dist/components/InkPanel.svelte.d.ts.map +1 -0
- package/dist/components/InkPrintButton.svelte +57 -0
- package/dist/components/InkPrintButton.svelte.d.ts +12 -0
- package/dist/components/InkPrintButton.svelte.d.ts.map +1 -0
- package/dist/components/InkRecordList.svelte +91 -0
- package/dist/components/InkRecordList.svelte.d.ts +72 -0
- package/dist/components/InkRecordList.svelte.d.ts.map +1 -0
- package/dist/components/InkRoot.svelte +53 -5
- package/dist/components/InkRoot.svelte.d.ts +7 -2
- package/dist/components/InkRoot.svelte.d.ts.map +1 -1
- package/dist/components/InkSearchResults.svelte +72 -0
- package/dist/components/InkSearchResults.svelte.d.ts +9 -0
- package/dist/components/InkSearchResults.svelte.d.ts.map +1 -0
- package/dist/components/InkShapeMenu.svelte +89 -84
- package/dist/components/InkShapeMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkSidebar.svelte +179 -0
- package/dist/components/InkSidebar.svelte.d.ts +22 -0
- package/dist/components/InkSidebar.svelte.d.ts.map +1 -0
- package/dist/components/InkSignatureDialog.svelte +7 -3
- package/dist/components/InkSignatureDialog.svelte.d.ts +4 -3
- package/dist/components/InkSignatureDialog.svelte.d.ts.map +1 -1
- package/dist/components/InkSignatureMenu.svelte +85 -77
- package/dist/components/InkSignatureMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkThumbnail.svelte +74 -0
- package/dist/components/InkThumbnail.svelte.d.ts +19 -0
- package/dist/components/InkThumbnail.svelte.d.ts.map +1 -0
- package/dist/components/InkThumbnails.svelte +146 -0
- package/dist/components/InkThumbnails.svelte.d.ts +24 -0
- package/dist/components/InkThumbnails.svelte.d.ts.map +1 -0
- package/dist/components/InkToolButton.svelte +23 -24
- package/dist/components/InkToolButton.svelte.d.ts.map +1 -1
- package/dist/components/InkToolbarButton.svelte +33 -0
- package/dist/components/InkToolbarButton.svelte.d.ts +12 -0
- package/dist/components/InkToolbarButton.svelte.d.ts.map +1 -0
- package/dist/components/InkViewport.svelte +4 -0
- package/dist/components/InkViewport.svelte.d.ts.map +1 -1
- package/dist/components/InkZoomSelect.svelte +1 -1
- package/dist/components/RecordCards.svelte +173 -0
- package/dist/components/RecordCards.svelte.d.ts +16 -0
- package/dist/components/RecordCards.svelte.d.ts.map +1 -0
- package/dist/components/SidebarTrigger.svelte +20 -0
- package/dist/components/SidebarTrigger.svelte.d.ts +9 -0
- package/dist/components/SidebarTrigger.svelte.d.ts.map +1 -0
- package/dist/components/SignatureForm.svelte +9 -3
- package/dist/components/SignatureForm.svelte.d.ts.map +1 -1
- package/dist/components/body-lock.d.ts +3 -0
- package/dist/components/body-lock.d.ts.map +1 -0
- package/dist/components/body-lock.js +43 -0
- package/dist/components/sidebar-context.d.ts +24 -0
- package/dist/components/sidebar-context.d.ts.map +1 -0
- package/dist/components/sidebar-context.js +13 -0
- package/dist/context.d.ts +6 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/hooks/useAnnotations.svelte.d.ts +78 -0
- package/dist/hooks/useAnnotations.svelte.d.ts.map +1 -1
- package/dist/hooks/useRecordSelection.svelte.d.ts +11 -0
- package/dist/hooks/useRecordSelection.svelte.d.ts.map +1 -0
- package/dist/hooks/useRecordSelection.svelte.js +19 -0
- package/dist/hooks/useRecords.svelte.d.ts +14 -0
- package/dist/hooks/useRecords.svelte.d.ts.map +1 -0
- package/dist/hooks/useRecords.svelte.js +24 -0
- package/dist/hooks/useRegisteredTool.svelte.d.ts +24 -0
- package/dist/hooks/useRegisteredTool.svelte.d.ts.map +1 -0
- package/dist/hooks/useRegisteredTool.svelte.js +47 -0
- package/dist/hooks/useSearch.svelte.d.ts.map +1 -1
- package/dist/hooks/useSearch.svelte.js +1 -0
- package/dist/hooks/useToolOptions.svelte.d.ts +8 -0
- package/dist/hooks/useToolOptions.svelte.d.ts.map +1 -1
- package/dist/hooks/useToolOptions.svelte.js +12 -2
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/to-readable.svelte.d.ts +8 -0
- package/dist/to-readable.svelte.d.ts.map +1 -0
- package/dist/to-readable.svelte.js +15 -0
- package/package.json +5 -5
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
import { ChevronDown } from '@inkbar/icons'
|
|
30
30
|
import { Popover, Toolbar } from 'bits-ui'
|
|
31
31
|
|
|
32
|
+
import { useRegisteredTool } from '../hooks/useRegisteredTool.svelte.js'
|
|
32
33
|
import { useTool } from '../hooks/useTool.svelte.js'
|
|
33
|
-
import {
|
|
34
|
+
import { useToolOptionsWhile } from '../hooks/useToolOptions.svelte.js'
|
|
34
35
|
|
|
35
36
|
import InkIcon from './InkIcon.svelte'
|
|
36
37
|
import { createMenuOpenFocus } from './menu-open-focus.js'
|
|
@@ -38,7 +39,9 @@
|
|
|
38
39
|
let { class: className, children, ...rest }: InkShapeMenuProps = $props()
|
|
39
40
|
|
|
40
41
|
const current = useTool()
|
|
41
|
-
|
|
42
|
+
// Nothing renders while no `shape` tool is registered.
|
|
43
|
+
const registered = useRegisteredTool('shape')
|
|
44
|
+
const shape = useToolOptionsWhile<ShapeOptions>('shape', () => registered.current)
|
|
42
45
|
let open = $state(false)
|
|
43
46
|
/** The split button: the panel lines up under it rather than the chevron. */
|
|
44
47
|
let group = $state<HTMLElement | null>(null)
|
|
@@ -67,88 +70,90 @@
|
|
|
67
70
|
}
|
|
68
71
|
</script>
|
|
69
72
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<Toolbar.Button
|
|
79
|
-
class="ink-tool-button ink-shape-button"
|
|
80
|
-
data-ink-tool-button=""
|
|
81
|
-
data-ink-shape-button=""
|
|
82
|
-
data-tool="shape"
|
|
83
|
-
data-kind={model.kind}
|
|
84
|
-
data-state={active ? 'on' : 'off'}
|
|
85
|
-
aria-pressed={active}
|
|
86
|
-
aria-label={model.label}
|
|
87
|
-
title={model.label}
|
|
88
|
-
onclick={() => current.setTool('shape')}
|
|
73
|
+
{#if registered.current}
|
|
74
|
+
<div
|
|
75
|
+
bind:this={group}
|
|
76
|
+
role="group"
|
|
77
|
+
aria-label="Shape"
|
|
78
|
+
class={['ink-split-button ink-shape-menu', className]}
|
|
79
|
+
data-ink-shape-menu=""
|
|
80
|
+
{...rest}
|
|
89
81
|
>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
>
|
|
128
|
-
<div
|
|
129
|
-
role="group"
|
|
82
|
+
<Toolbar.Button
|
|
83
|
+
class="ink-tool-button ink-shape-button"
|
|
84
|
+
data-ink-tool-button=""
|
|
85
|
+
data-ink-shape-button=""
|
|
86
|
+
data-tool="shape"
|
|
87
|
+
data-kind={model.kind}
|
|
88
|
+
data-state={active ? 'on' : 'off'}
|
|
89
|
+
aria-pressed={active}
|
|
90
|
+
aria-label={model.label}
|
|
91
|
+
title={model.label}
|
|
92
|
+
onclick={() => current.setTool('shape')}
|
|
93
|
+
>
|
|
94
|
+
{#if children}{@render children()}{:else}<InkIcon
|
|
95
|
+
icon={SHAPE_ICONS[model.kind]}
|
|
96
|
+
/>{/if}
|
|
97
|
+
</Toolbar.Button>
|
|
98
|
+
<Popover.Root bind:open>
|
|
99
|
+
<Popover.Trigger>
|
|
100
|
+
{#snippet child({ props })}
|
|
101
|
+
<Toolbar.Button
|
|
102
|
+
{...props}
|
|
103
|
+
class="ink-menu-trigger ink-shape-menu-trigger"
|
|
104
|
+
data-ink-shape-menu-trigger=""
|
|
105
|
+
data-state={open ? 'open' : 'closed'}
|
|
106
|
+
aria-label="Choose shape"
|
|
107
|
+
title="Choose shape"
|
|
108
|
+
aria-haspopup="menu"
|
|
109
|
+
onkeydown={onTriggerKeydown}
|
|
110
|
+
>
|
|
111
|
+
<InkIcon icon={ChevronDown} />
|
|
112
|
+
</Toolbar.Button>
|
|
113
|
+
{/snippet}
|
|
114
|
+
</Popover.Trigger>
|
|
115
|
+
<Popover.Portal>
|
|
116
|
+
<Popover.Content
|
|
117
|
+
bind:ref={menu}
|
|
118
|
+
role="menu"
|
|
130
119
|
aria-label="Shapes"
|
|
131
|
-
class="ink-
|
|
132
|
-
data-ink-
|
|
120
|
+
class="ink-select-content ink-menu-content"
|
|
121
|
+
data-ink-select-content=""
|
|
122
|
+
data-ink-menu="shape"
|
|
123
|
+
customAnchor={group}
|
|
124
|
+
side="bottom"
|
|
125
|
+
align="start"
|
|
126
|
+
sideOffset={4}
|
|
127
|
+
collisionPadding={8}
|
|
128
|
+
onOpenAutoFocus={(e) => openFocus.onOpenAutoFocus(e, menu)}
|
|
129
|
+
onfocusin={openFocus.onfocusin}
|
|
130
|
+
onkeydown={(e) => menu && handleMenuKeys(e, menu)}
|
|
133
131
|
>
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
</
|
|
132
|
+
<div
|
|
133
|
+
role="group"
|
|
134
|
+
aria-label="Shapes"
|
|
135
|
+
class="ink-shape-grid"
|
|
136
|
+
data-ink-menu-columns={SHAPE_COLUMNS}
|
|
137
|
+
>
|
|
138
|
+
{#each model.items as item (item.kind)}
|
|
139
|
+
<button
|
|
140
|
+
type="button"
|
|
141
|
+
role="menuitemradio"
|
|
142
|
+
class="ink-select-item ink-menu-item ink-shape-item"
|
|
143
|
+
data-ink-select-item=""
|
|
144
|
+
tabindex={-1}
|
|
145
|
+
data-key={item.kind}
|
|
146
|
+
aria-checked={item.checked}
|
|
147
|
+
data-state={item.checked ? 'checked' : 'unchecked'}
|
|
148
|
+
onclick={() => choose(item.kind)}
|
|
149
|
+
>
|
|
150
|
+
<InkIcon icon={SHAPE_ICONS[item.kind]} size={16} />
|
|
151
|
+
{item.label}
|
|
152
|
+
</button>
|
|
153
|
+
{/each}
|
|
154
|
+
</div>
|
|
155
|
+
</Popover.Content>
|
|
156
|
+
</Popover.Portal>
|
|
157
|
+
</Popover.Root>
|
|
158
|
+
</div>
|
|
159
|
+
{/if}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkShapeMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkShapeMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/B;
|
|
1
|
+
{"version":3,"file":"InkShapeMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkShapeMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/B;AAqGH,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { SidebarLayout, SidebarOpen, SidebarSide } from '@inkbar/core/dom'
|
|
3
|
+
import type { Snippet } from 'svelte'
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
5
|
+
|
|
6
|
+
export interface InkSidebarProps extends Omit<
|
|
7
|
+
HTMLAttributes<HTMLDivElement>,
|
|
8
|
+
'children'
|
|
9
|
+
> {
|
|
10
|
+
/** Which edge the rail and border sit on. Default `'left'`. */
|
|
11
|
+
side?: SidebarSide | undefined
|
|
12
|
+
/** `'rail'` (default), `'tabs'` or `'stack'`. */
|
|
13
|
+
layout?: SidebarLayout | undefined
|
|
14
|
+
/** Default true. False hides the whole sidebar and keeps its open panel, content and scroll for when it shows again. */
|
|
15
|
+
visible?: boolean | undefined
|
|
16
|
+
/**
|
|
17
|
+
* Bindable: the open panel's id (or null) for rail and tabs, the expanded ids for stack.
|
|
18
|
+
* Left out, the first panel starts open.
|
|
19
|
+
*/
|
|
20
|
+
open?: SidebarOpen | undefined
|
|
21
|
+
/** The `InkPanel`s. */
|
|
22
|
+
children?: Snippet | undefined
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script lang="ts">
|
|
27
|
+
/*
|
|
28
|
+
* A sidebar of `InkPanel`s: `createSidebar`'s markup on core's sidebar controller, which holds
|
|
29
|
+
* the open state, the ARIA, the keys and the clicks. Rail and tabs render their triggers here;
|
|
30
|
+
* in a stack each panel renders its own header. Panels register as they initialise and take
|
|
31
|
+
* their place in DOM order once mounted, so a panel added later with `{#if}` slots in where
|
|
32
|
+
* it stands. A closed panel stays mounted and hidden, and the panels' content stays in place
|
|
33
|
+
* across layouts, so its state survives switching.
|
|
34
|
+
*
|
|
35
|
+
* `bind:open` is the open panel's id (or null) for rail and tabs, and the expanded ids for
|
|
36
|
+
* stack. Left out, the first panel starts open. It needs no document, so it works outside
|
|
37
|
+
* `InkRoot`. The server renders the root, the panels (the open one shown) and the stack
|
|
38
|
+
* headers; rail and tab buttons follow once mounted, as the panels register after the root
|
|
39
|
+
* has rendered.
|
|
40
|
+
*/
|
|
41
|
+
import { createSidebarController } from '@inkbar/core/dom'
|
|
42
|
+
import { untrack } from 'svelte'
|
|
43
|
+
|
|
44
|
+
import { useReadable } from '../use-readable.svelte.js'
|
|
45
|
+
|
|
46
|
+
import { setSidebarContext, type SidebarPanelEntry } from './sidebar-context.js'
|
|
47
|
+
import SidebarTrigger from './SidebarTrigger.svelte'
|
|
48
|
+
|
|
49
|
+
let {
|
|
50
|
+
side = 'left',
|
|
51
|
+
layout = 'rail',
|
|
52
|
+
visible = true,
|
|
53
|
+
open = $bindable(),
|
|
54
|
+
class: className,
|
|
55
|
+
children,
|
|
56
|
+
...rest
|
|
57
|
+
}: InkSidebarProps = $props()
|
|
58
|
+
|
|
59
|
+
// The same ids on the server and the client.
|
|
60
|
+
const idPrefix = $props.id()
|
|
61
|
+
|
|
62
|
+
let entries = $state.raw<SidebarPanelEntry[]>([])
|
|
63
|
+
const infos = () => entries.map((e) => e.info())
|
|
64
|
+
|
|
65
|
+
// Pending until mounted: the panels register one by one as they initialise, and an open id
|
|
66
|
+
// not registered yet is not a removed panel.
|
|
67
|
+
const controller = untrack(() =>
|
|
68
|
+
createSidebarController({
|
|
69
|
+
layout,
|
|
70
|
+
side,
|
|
71
|
+
visible,
|
|
72
|
+
panels: [],
|
|
73
|
+
...(open !== undefined && { open }),
|
|
74
|
+
pending: true,
|
|
75
|
+
onOpenChange: (value) => {
|
|
76
|
+
open = value
|
|
77
|
+
},
|
|
78
|
+
idPrefix,
|
|
79
|
+
})
|
|
80
|
+
)
|
|
81
|
+
const current = useReadable(() => controller.state, controller.state.get())
|
|
82
|
+
// Destroyed before the panels go: this pre-effect comes before the template's, so its
|
|
83
|
+
// teardown runs first. Unregistering into a live controller would take each panel for a
|
|
84
|
+
// removed one and write the fallback to the bound `open`.
|
|
85
|
+
$effect.pre(() => () => controller.destroy())
|
|
86
|
+
|
|
87
|
+
// Before the DOM updates, so the panels render the attributes these give.
|
|
88
|
+
$effect.pre(() => {
|
|
89
|
+
const next = { layout, side, visible, open }
|
|
90
|
+
untrack(() =>
|
|
91
|
+
controller.update({
|
|
92
|
+
layout: next.layout,
|
|
93
|
+
side: next.side,
|
|
94
|
+
visible: next.visible,
|
|
95
|
+
...(next.open !== undefined && { open: next.open }),
|
|
96
|
+
})
|
|
97
|
+
)
|
|
98
|
+
})
|
|
99
|
+
// A panel's label, icon or badge changing.
|
|
100
|
+
$effect.pre(() => {
|
|
101
|
+
const panels = infos()
|
|
102
|
+
untrack(() => controller.update({ panels }))
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// Panels register while they initialise, inside the parent's render: untracked, so the
|
|
106
|
+
// writes are not taken for state changed by a template expression. On the server too.
|
|
107
|
+
function register(entry: SidebarPanelEntry): () => void {
|
|
108
|
+
untrack(() => {
|
|
109
|
+
entries = [...entries, entry]
|
|
110
|
+
controller.update({ panels: infos() })
|
|
111
|
+
})
|
|
112
|
+
return () =>
|
|
113
|
+
untrack(() => {
|
|
114
|
+
entries = entries.filter((e) => e !== entry)
|
|
115
|
+
controller.update({ panels: infos() })
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function arrange(): void {
|
|
120
|
+
untrack(() => {
|
|
121
|
+
const list = entries
|
|
122
|
+
const sorted = [...list].sort((a, b) => {
|
|
123
|
+
const x = a.element()
|
|
124
|
+
const y = b.element()
|
|
125
|
+
if (!x || !y || x === y) return 0
|
|
126
|
+
return x.compareDocumentPosition(y) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
|
|
127
|
+
})
|
|
128
|
+
if (sorted.some((e, i) => e !== list[i])) {
|
|
129
|
+
entries = sorted
|
|
130
|
+
controller.update({ panels: infos() })
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
setSidebarContext({ controller, state: current, register, arrange })
|
|
136
|
+
|
|
137
|
+
const view = $derived.by(() => {
|
|
138
|
+
const s = current.current
|
|
139
|
+
return {
|
|
140
|
+
layout: s.layout,
|
|
141
|
+
root: controller.rootAttrs(),
|
|
142
|
+
tablist: controller.tablistAttrs(),
|
|
143
|
+
triggers: s.panels.map((panel) => ({
|
|
144
|
+
panel,
|
|
145
|
+
attrs: controller.triggerAttrs(panel.id),
|
|
146
|
+
})),
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
let root = $state<HTMLDivElement | null>(null)
|
|
151
|
+
// The controller handles the triggers' clicks and keys, stack headers included. The panels
|
|
152
|
+
// have registered by now.
|
|
153
|
+
$effect(() => {
|
|
154
|
+
const el = root
|
|
155
|
+
if (!el) return
|
|
156
|
+
const unbind = untrack(() => controller.bindTriggers(el))
|
|
157
|
+
untrack(() => controller.update({ pending: false }))
|
|
158
|
+
return unbind
|
|
159
|
+
})
|
|
160
|
+
</script>
|
|
161
|
+
|
|
162
|
+
<div {...rest} bind:this={root} class={['ink-sidebar', className]} {...view.root}>
|
|
163
|
+
{#if view.layout !== 'stack'}
|
|
164
|
+
<div
|
|
165
|
+
class={view.layout === 'rail' ? 'ink-sidebar-rail' : 'ink-sidebar-tabs'}
|
|
166
|
+
{...view.tablist}
|
|
167
|
+
>
|
|
168
|
+
{#each view.triggers as t (t.panel.id)}
|
|
169
|
+
<button {...t.attrs}>
|
|
170
|
+
<SidebarTrigger panel={t.panel} rail={view.layout === 'rail'} />
|
|
171
|
+
</button>
|
|
172
|
+
{/each}
|
|
173
|
+
</div>
|
|
174
|
+
{/if}
|
|
175
|
+
<!-- One element in every layout, so the panels are never remounted. -->
|
|
176
|
+
<div class={{ 'ink-sidebar-panels': view.layout !== 'stack' }}>
|
|
177
|
+
{@render children?.()}
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SidebarLayout, SidebarOpen, SidebarSide } from '@inkbar/core/dom';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
export interface InkSidebarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
5
|
+
/** Which edge the rail and border sit on. Default `'left'`. */
|
|
6
|
+
side?: SidebarSide | undefined;
|
|
7
|
+
/** `'rail'` (default), `'tabs'` or `'stack'`. */
|
|
8
|
+
layout?: SidebarLayout | undefined;
|
|
9
|
+
/** Default true. False hides the whole sidebar and keeps its open panel, content and scroll for when it shows again. */
|
|
10
|
+
visible?: boolean | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Bindable: the open panel's id (or null) for rail and tabs, the expanded ids for stack.
|
|
13
|
+
* Left out, the first panel starts open.
|
|
14
|
+
*/
|
|
15
|
+
open?: SidebarOpen | undefined;
|
|
16
|
+
/** The `InkPanel`s. */
|
|
17
|
+
children?: Snippet | undefined;
|
|
18
|
+
}
|
|
19
|
+
declare const InkSidebar: import("svelte").Component<InkSidebarProps, {}, "open">;
|
|
20
|
+
type InkSidebar = ReturnType<typeof InkSidebar>;
|
|
21
|
+
export default InkSidebar;
|
|
22
|
+
//# sourceMappingURL=InkSidebar.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InkSidebar.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSidebar.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IAC9B,iDAAiD;IACjD,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;IAClC,wHAAwH;IACxH,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IAC9B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/B;AAwKH,QAAA,MAAM,UAAU,yDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* "Create signature": a modal with Draw, Type and Image tabs. Draw is a pad with the draw
|
|
6
6
|
* tool's renderer; Type sets a name in one of the host's handwriting fonts; Image takes a PNG
|
|
7
7
|
* or JPEG scan. Save stores the template through InkRoot's signature store and, unless
|
|
8
|
-
* `select` is false, selects it for
|
|
8
|
+
* `select` is false or no `signature` tool is registered, selects it for that tool. Escape, Cancel or a press outside
|
|
9
9
|
* closes it.
|
|
10
10
|
*/
|
|
11
11
|
export interface InkSignatureDialogProps {
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
/** The fonts the Type tab offers. Default: InkRoot's `signatureFonts`. */
|
|
15
15
|
fonts?: readonly string[] | undefined
|
|
16
16
|
/**
|
|
17
|
-
* Whether saving selects the new signature for the `signature` tool
|
|
18
|
-
* leaves the tool alone, for a dialog that signs a field
|
|
17
|
+
* Whether saving selects the new signature for the `signature` tool, when one is
|
|
18
|
+
* registered. Default true. False leaves the tool alone, for a dialog that signs a field
|
|
19
|
+
* with it through `onSave`.
|
|
19
20
|
*/
|
|
20
21
|
select?: boolean | undefined
|
|
21
22
|
/** Called with the new template once it is saved (and selected, with `select`). */
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
import { SIGNATURE_LABELS } from '@inkbar/core/dom'
|
|
31
32
|
import { Dialog } from 'bits-ui'
|
|
32
33
|
|
|
34
|
+
import { lockBody } from './body-lock.js'
|
|
33
35
|
import SignatureForm from './SignatureForm.svelte'
|
|
34
36
|
|
|
35
37
|
let {
|
|
@@ -58,6 +60,8 @@
|
|
|
58
60
|
class={['ink-dialog ink-signature-dialog', className]}
|
|
59
61
|
data-ink-signature-dialog=""
|
|
60
62
|
aria-modal="true"
|
|
63
|
+
preventScroll={false}
|
|
64
|
+
{@attach lockBody}
|
|
61
65
|
onOpenAutoFocus={(e) => {
|
|
62
66
|
e.preventDefault()
|
|
63
67
|
content
|
|
@@ -3,7 +3,7 @@ import type { SignatureTemplate } from '@inkbar/core';
|
|
|
3
3
|
* "Create signature": a modal with Draw, Type and Image tabs. Draw is a pad with the draw
|
|
4
4
|
* tool's renderer; Type sets a name in one of the host's handwriting fonts; Image takes a PNG
|
|
5
5
|
* or JPEG scan. Save stores the template through InkRoot's signature store and, unless
|
|
6
|
-
* `select` is false, selects it for
|
|
6
|
+
* `select` is false or no `signature` tool is registered, selects it for that tool. Escape, Cancel or a press outside
|
|
7
7
|
* closes it.
|
|
8
8
|
*/
|
|
9
9
|
export interface InkSignatureDialogProps {
|
|
@@ -12,8 +12,9 @@ export interface InkSignatureDialogProps {
|
|
|
12
12
|
/** The fonts the Type tab offers. Default: InkRoot's `signatureFonts`. */
|
|
13
13
|
fonts?: readonly string[] | undefined;
|
|
14
14
|
/**
|
|
15
|
-
* Whether saving selects the new signature for the `signature` tool
|
|
16
|
-
* leaves the tool alone, for a dialog that signs a field
|
|
15
|
+
* Whether saving selects the new signature for the `signature` tool, when one is
|
|
16
|
+
* registered. Default true. False leaves the tool alone, for a dialog that signs a field
|
|
17
|
+
* with it through `onSave`.
|
|
17
18
|
*/
|
|
18
19
|
select?: boolean | undefined;
|
|
19
20
|
/** Called with the new template once it is saved (and selected, with `select`). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkSignatureDialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureDialog.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACpD,0EAA0E;IAC1E,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC
|
|
1
|
+
{"version":3,"file":"InkSignatureDialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureDialog.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACpD,0EAA0E;IAC1E,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,mFAAmF;IACnF,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC5D,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACvD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC3B;AAqDH,QAAA,MAAM,kBAAkB,iEAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
import { untrack } from 'svelte'
|
|
27
27
|
|
|
28
28
|
import { useInkContext } from '../context.js'
|
|
29
|
+
import { useRegisteredTool } from '../hooks/useRegisteredTool.svelte.js'
|
|
29
30
|
import { useTool } from '../hooks/useTool.svelte.js'
|
|
30
|
-
import {
|
|
31
|
+
import { useToolOptionsWhile } from '../hooks/useToolOptions.svelte.js'
|
|
31
32
|
import { useReadable } from '../use-readable.svelte.js'
|
|
32
33
|
|
|
33
34
|
import InkIcon from './InkIcon.svelte'
|
|
@@ -43,7 +44,12 @@
|
|
|
43
44
|
|
|
44
45
|
const ctx = useInkContext('InkSignatureMenu')
|
|
45
46
|
const current = useTool()
|
|
46
|
-
|
|
47
|
+
// Nothing renders while no `signature` tool is registered.
|
|
48
|
+
const registered = useRegisteredTool('signature')
|
|
49
|
+
const signature = useToolOptionsWhile<SignatureOptions>(
|
|
50
|
+
'signature',
|
|
51
|
+
() => registered.current
|
|
52
|
+
)
|
|
47
53
|
const templates = useReadable(() => ctx.signatures.templates, NO_TEMPLATES)
|
|
48
54
|
// An old removal error is not news when the menu opens again.
|
|
49
55
|
$effect(() => {
|
|
@@ -91,81 +97,83 @@
|
|
|
91
97
|
}
|
|
92
98
|
</script>
|
|
93
99
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
class={['ink-split-button ink-signature-menu', className]}
|
|
99
|
-
data-ink-signature-menu=""
|
|
100
|
-
{...rest}
|
|
101
|
-
>
|
|
102
|
-
<Toolbar.Button
|
|
103
|
-
bind:ref={main}
|
|
104
|
-
class="ink-tool-button ink-signature-button"
|
|
105
|
-
data-ink-tool-button=""
|
|
106
|
-
data-ink-signature-button=""
|
|
107
|
-
data-tool="signature"
|
|
108
|
-
data-state={active ? 'on' : 'off'}
|
|
109
|
-
aria-pressed={active}
|
|
100
|
+
{#if registered.current}
|
|
101
|
+
<div
|
|
102
|
+
bind:this={group}
|
|
103
|
+
role="group"
|
|
110
104
|
aria-label={SIGNATURE_LABELS.sign}
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
class={['ink-split-button ink-signature-menu', className]}
|
|
106
|
+
data-ink-signature-menu=""
|
|
107
|
+
{...rest}
|
|
113
108
|
>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
109
|
+
<Toolbar.Button
|
|
110
|
+
bind:ref={main}
|
|
111
|
+
class="ink-tool-button ink-signature-button"
|
|
112
|
+
data-ink-tool-button=""
|
|
113
|
+
data-ink-signature-button=""
|
|
114
|
+
data-tool="signature"
|
|
115
|
+
data-state={active ? 'on' : 'off'}
|
|
116
|
+
aria-pressed={active}
|
|
117
|
+
aria-label={SIGNATURE_LABELS.sign}
|
|
118
|
+
title={SIGNATURE_LABELS.sign}
|
|
119
|
+
onclick={onMain}
|
|
120
|
+
>
|
|
121
|
+
{#if children}{@render children()}{:else}<InkIcon icon={Signature} />{/if}
|
|
122
|
+
</Toolbar.Button>
|
|
123
|
+
<Popover.Root bind:open>
|
|
124
|
+
<Popover.Trigger>
|
|
125
|
+
{#snippet child({ props })}
|
|
126
|
+
<Toolbar.Button
|
|
127
|
+
{...props}
|
|
128
|
+
class="ink-menu-trigger ink-signature-menu-trigger"
|
|
129
|
+
data-ink-signature-menu-trigger=""
|
|
130
|
+
data-state={open ? 'open' : 'closed'}
|
|
131
|
+
aria-label={SIGNATURE_LABELS.trigger}
|
|
132
|
+
title={SIGNATURE_LABELS.trigger}
|
|
133
|
+
aria-haspopup="menu"
|
|
134
|
+
onkeydown={onTriggerKeydown}
|
|
135
|
+
>
|
|
136
|
+
<InkIcon icon={ChevronDown} />
|
|
137
|
+
</Toolbar.Button>
|
|
138
|
+
{/snippet}
|
|
139
|
+
</Popover.Trigger>
|
|
140
|
+
<Popover.Portal>
|
|
141
|
+
<Popover.Content
|
|
142
|
+
bind:ref={menu}
|
|
143
|
+
role="menu"
|
|
144
|
+
aria-label={SIGNATURE_LABELS.menu}
|
|
145
|
+
class="ink-select-content ink-menu-content"
|
|
146
|
+
data-ink-select-content=""
|
|
147
|
+
data-ink-menu="signature"
|
|
148
|
+
customAnchor={group}
|
|
149
|
+
side="bottom"
|
|
150
|
+
align="start"
|
|
151
|
+
sideOffset={4}
|
|
152
|
+
collisionPadding={8}
|
|
153
|
+
onOpenAutoFocus={(e) => openFocus.onOpenAutoFocus(e, menu)}
|
|
154
|
+
onfocusin={openFocus.onfocusin}
|
|
155
|
+
onCloseAutoFocus={(e) => {
|
|
156
|
+
if (toDialog) e.preventDefault()
|
|
157
|
+
toDialog = false
|
|
158
|
+
}}
|
|
159
|
+
onkeydown={(e) => menu && handleMenuKeys(e, menu)}
|
|
128
160
|
>
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
onCloseAutoFocus={(e) => {
|
|
149
|
-
if (toDialog) e.preventDefault()
|
|
150
|
-
toDialog = false
|
|
151
|
-
}}
|
|
152
|
-
onkeydown={(e) => menu && handleMenuKeys(e, menu)}
|
|
153
|
-
>
|
|
154
|
-
<SignatureMenuPanel
|
|
155
|
-
items={model.items}
|
|
156
|
-
menu={() => menu}
|
|
157
|
-
onChoose={(t) => choose(t.id)}
|
|
158
|
-
onCreate={create}
|
|
159
|
-
/>
|
|
160
|
-
</Popover.Content>
|
|
161
|
-
</Popover.Portal>
|
|
162
|
-
</Popover.Root>
|
|
163
|
-
<InkSignatureDialog
|
|
164
|
-
bind:open={creating}
|
|
165
|
-
{fonts}
|
|
166
|
-
onCloseAutoFocus={(e) => {
|
|
167
|
-
e.preventDefault()
|
|
168
|
-
main?.focus({ preventScroll: true })
|
|
169
|
-
}}
|
|
170
|
-
/>
|
|
171
|
-
</div>
|
|
161
|
+
<SignatureMenuPanel
|
|
162
|
+
items={model.items}
|
|
163
|
+
menu={() => menu}
|
|
164
|
+
onChoose={(t) => choose(t.id)}
|
|
165
|
+
onCreate={create}
|
|
166
|
+
/>
|
|
167
|
+
</Popover.Content>
|
|
168
|
+
</Popover.Portal>
|
|
169
|
+
</Popover.Root>
|
|
170
|
+
<InkSignatureDialog
|
|
171
|
+
bind:open={creating}
|
|
172
|
+
{fonts}
|
|
173
|
+
onCloseAutoFocus={(e) => {
|
|
174
|
+
e.preventDefault()
|
|
175
|
+
main?.focus({ preventScroll: true })
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
{/if}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkSignatureMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CACjD,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,mFAAmF;IACnF,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACtC;
|
|
1
|
+
{"version":3,"file":"InkSignatureMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CACjD,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,mFAAmF;IACnF,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACtC;AAoIH,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|