@dosgato/dialog 1.1.19 → 1.1.21
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/Container.svelte +3 -3
- package/dist/FieldChoices.svelte +1 -1
- package/dist/FieldRadio.svelte +2 -2
- package/dist/cropper/FieldCropper.svelte +14 -1
- package/dist/cropper/cropper.d.ts +1 -0
- package/dist/cropper/cropper.js +3 -0
- package/dist/iconpicker/FieldIconPicker.svelte +20 -5
- package/dist/imageposition/FieldImagePosition.svelte +193 -0
- package/dist/imageposition/FieldImagePosition.svelte.d.ts +25 -0
- package/dist/imageposition/index.d.ts +2 -0
- package/dist/imageposition/index.js +2 -0
- package/dist/imageposition/position.d.ts +4 -0
- package/dist/imageposition/position.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +2 -2
package/dist/Container.svelte
CHANGED
|
@@ -60,10 +60,10 @@ onDestroy(() => {
|
|
|
60
60
|
{#if helptext}
|
|
61
61
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
62
62
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
63
|
-
<div use:resize={{ debounce: 10 }} on:resize={setNeedsShowHelp}
|
|
64
|
-
<span bind:this={helpelement}>{@html helptext}</span>
|
|
63
|
+
<div use:resize={{ debounce: 10 }} on:resize={setNeedsShowHelp} class="dialog-field-help" class:needsShowHelp class:expanded={showhelp} on:click={() => { if (needsShowHelp) showhelp = !showhelp }}>
|
|
64
|
+
<span bind:this={helpelement} id={helptextid}>{@html helptext}</span>
|
|
65
65
|
{#if needsShowHelp}
|
|
66
|
-
<button type="button" class="dialog-field-help-expand">Show {#if showhelp}Less{:else}More{/if}<ScreenReaderOnly>, ignore this, the help text it controls will be read to you as input description</ScreenReaderOnly></button>
|
|
66
|
+
<button type="button" class="dialog-field-help-expand">Show {#if showhelp}Less{:else}More{/if}<ScreenReaderOnly>, ignore this, the help text it controls will be fully read to you as input description</ScreenReaderOnly></button>
|
|
67
67
|
{/if}
|
|
68
68
|
</div>
|
|
69
69
|
{/if}
|
package/dist/FieldChoices.svelte
CHANGED
|
@@ -49,7 +49,7 @@ function onChangeCheckbox(setVal, choice, included) {
|
|
|
49
49
|
}
|
|
50
50
|
const descid = randomid();
|
|
51
51
|
function reactToChoices(..._) {
|
|
52
|
-
const choiceSet = new Set(choices?.map(c => c.value));
|
|
52
|
+
const choiceSet = new Set(choices?.filter(c => !c.disabled).map(c => c.value));
|
|
53
53
|
const val = get($store, finalPath);
|
|
54
54
|
const filtered = val?.filter(v => choiceSet.has(v));
|
|
55
55
|
if (filtered?.length !== val?.length)
|
package/dist/FieldRadio.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>import { FORM_CONTEXT, FORM_INHERITED_PATH, Field } from '@txstate-mws/svelte-forms';
|
|
2
2
|
import { getContext, onMount } from 'svelte';
|
|
3
|
-
import { get, isNotBlank } from 'txstate-utils';
|
|
3
|
+
import { equal, get, isNotBlank } from 'txstate-utils';
|
|
4
4
|
import Switcher from './Switcher.svelte';
|
|
5
5
|
let className = '';
|
|
6
6
|
export { className as class };
|
|
@@ -36,7 +36,7 @@ async function reactToChoices(..._) {
|
|
|
36
36
|
return await store.setField(finalPath, finalDeserialize(''));
|
|
37
37
|
}
|
|
38
38
|
const val = get($store.data, finalPath);
|
|
39
|
-
if (!choices.some(o => o.value
|
|
39
|
+
if (!choices.some(o => equal(o.value, val)))
|
|
40
40
|
await store.setField(finalPath, notNull ? defaultValue : finalDeserialize(''));
|
|
41
41
|
}
|
|
42
42
|
$: reactToChoices(choices).catch(console.error);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script>import { resize, ScreenReaderOnly } from '@txstate-mws/svelte-components';
|
|
2
|
-
import { onMount } from 'svelte';
|
|
2
|
+
import { onMount, tick } from 'svelte';
|
|
3
3
|
import { isNotBlank, randomid } from 'txstate-utils';
|
|
4
4
|
import FieldStandard from '../FieldStandard.svelte';
|
|
5
5
|
import { CropperStore } from './cropper';
|
|
@@ -16,6 +16,7 @@ const store = new CropperStore({ width: 0, height: 0, minSelection, targetAspect
|
|
|
16
16
|
const { output, outputPct, selection } = store;
|
|
17
17
|
let setVal;
|
|
18
18
|
let value;
|
|
19
|
+
const initialAspectRatio = selectionAspectRatio;
|
|
19
20
|
function init(spValue, spSetVal) {
|
|
20
21
|
setVal = spSetVal;
|
|
21
22
|
value = spValue;
|
|
@@ -114,6 +115,18 @@ $: updateRect(container);
|
|
|
114
115
|
const descid = randomid();
|
|
115
116
|
const movedescid = randomid();
|
|
116
117
|
let focusWithin = false;
|
|
118
|
+
let arChanged = false;
|
|
119
|
+
async function reactToAspectRatio(ar) {
|
|
120
|
+
if (!ar)
|
|
121
|
+
return;
|
|
122
|
+
store.updateTargetAspect(ar);
|
|
123
|
+
await tick();
|
|
124
|
+
if (ar !== initialAspectRatio || arChanged) {
|
|
125
|
+
store.maximize();
|
|
126
|
+
arChanged = true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
$: void reactToAspectRatio(selectionAspectRatio);
|
|
117
130
|
</script>
|
|
118
131
|
|
|
119
132
|
<svelte:window on:mousemove={onMouseMove} on:mouseup={onMouseUp} on:touchend={onMouseUp} on:touchcancel={onMouseUp} />
|
|
@@ -49,6 +49,7 @@ export declare class CropperStore extends Store<ICropperStore> {
|
|
|
49
49
|
constructor(initialValue: Omit<ICropperStore, 'cursor'>);
|
|
50
50
|
setOutput(selection?: CropOutput): void;
|
|
51
51
|
updateDimensions(width: number, height: number): void;
|
|
52
|
+
updateTargetAspect(ar: number): void;
|
|
52
53
|
/**
|
|
53
54
|
* The svelte component is responsible for making sure x and y are relative to the drawing area,
|
|
54
55
|
* e.g. (0, 0) is the top left corner of the drawing area
|
package/dist/cropper/cropper.js
CHANGED
|
@@ -18,6 +18,9 @@ export class CropperStore extends Store {
|
|
|
18
18
|
updateDimensions(width, height) {
|
|
19
19
|
this.update(v => ({ ...v, width, height }));
|
|
20
20
|
}
|
|
21
|
+
updateTargetAspect(ar) {
|
|
22
|
+
this.update(v => ({ ...v, targetAspect: ar }));
|
|
23
|
+
}
|
|
21
24
|
/**
|
|
22
25
|
* The svelte component is responsible for making sure x and y are relative to the drawing area,
|
|
23
26
|
* e.g. (0, 0) is the top left corner of the drawing area
|
|
@@ -221,7 +221,7 @@ function onKeyDown(e) {
|
|
|
221
221
|
border-radius: 10px;
|
|
222
222
|
border: 1px solid #999;
|
|
223
223
|
height: 30px;
|
|
224
|
-
padding:
|
|
224
|
+
padding: 0.5em;
|
|
225
225
|
font-family: 'Nunito Sans', sans-serif !important;
|
|
226
226
|
}
|
|
227
227
|
|
|
@@ -234,18 +234,33 @@ function onKeyDown(e) {
|
|
|
234
234
|
|
|
235
235
|
/* Styles for the icon picker grid */
|
|
236
236
|
|
|
237
|
-
.icon-picker-items{
|
|
237
|
+
.icon-picker-items {
|
|
238
238
|
margin-top: 5px;
|
|
239
239
|
padding: 5px;
|
|
240
|
+
display: grid;
|
|
241
|
+
grid-template-columns: repeat(7, 1fr);
|
|
242
|
+
row-gap: 1em;
|
|
243
|
+
column-gap: 1em;
|
|
244
|
+
justify-items: center;
|
|
245
|
+
align-items: center;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@media (max-width: 800px) {
|
|
249
|
+
.icon-picker-items {
|
|
250
|
+
grid-template-columns: repeat(5, 1fr);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@media (max-width: 500px) {
|
|
255
|
+
.icon-picker-items {
|
|
256
|
+
grid-template-columns: repeat(4, 1fr);
|
|
257
|
+
}
|
|
240
258
|
}
|
|
241
259
|
|
|
242
260
|
.icon-picker-item {
|
|
243
|
-
float: left;
|
|
244
|
-
margin: 0px 11px 12px 11px;
|
|
245
261
|
text-align: center;
|
|
246
262
|
cursor: pointer;
|
|
247
263
|
color: inherit;
|
|
248
|
-
width: 10%;
|
|
249
264
|
position: relative;
|
|
250
265
|
font-size: 28px;
|
|
251
266
|
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<script>import { isNotBlank, randomid } from 'txstate-utils';
|
|
2
|
+
import FieldStandard from '../FieldStandard.svelte';
|
|
3
|
+
import Button from '../Button.svelte';
|
|
4
|
+
import arrowsIn from '@iconify-icons/ph/arrows-in';
|
|
5
|
+
import { Dialog } from '..';
|
|
6
|
+
import { onMount } from 'svelte';
|
|
7
|
+
import { modifierKey, ScreenReaderOnly } from '@txstate-mws/svelte-components';
|
|
8
|
+
export let id = undefined;
|
|
9
|
+
export let path;
|
|
10
|
+
export let imageSrc;
|
|
11
|
+
export let label = '';
|
|
12
|
+
export let required = false;
|
|
13
|
+
export let conditional = undefined;
|
|
14
|
+
export let helptext = undefined;
|
|
15
|
+
export let info = undefined;
|
|
16
|
+
export let defaultValue = { x: 50, y: 50 };
|
|
17
|
+
let initialVal;
|
|
18
|
+
function init(v) {
|
|
19
|
+
if (v) {
|
|
20
|
+
initialVal = v;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
initialVal = defaultValue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const boxes = [];
|
|
27
|
+
const descid = randomid();
|
|
28
|
+
const labelid = randomid();
|
|
29
|
+
let modalOpen = false;
|
|
30
|
+
function showModal() {
|
|
31
|
+
modalOpen = true;
|
|
32
|
+
}
|
|
33
|
+
function hideModal() {
|
|
34
|
+
modalOpen = false;
|
|
35
|
+
}
|
|
36
|
+
let x, y;
|
|
37
|
+
onMount(() => {
|
|
38
|
+
x = initialVal?.x / 25;
|
|
39
|
+
y = initialVal?.y / 25;
|
|
40
|
+
});
|
|
41
|
+
function onSave(setVal) {
|
|
42
|
+
setVal({ x: x * 25, y: y * 25 });
|
|
43
|
+
hideModal();
|
|
44
|
+
}
|
|
45
|
+
function onSelectBox(newX, newY) {
|
|
46
|
+
x = newX;
|
|
47
|
+
y = newY;
|
|
48
|
+
boxes[x + y * 5].focus();
|
|
49
|
+
}
|
|
50
|
+
function onKeyDown(e) {
|
|
51
|
+
if (modifierKey(e))
|
|
52
|
+
return;
|
|
53
|
+
if (e.key === 'ArrowDown') {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
y = Math.min(y + 1, 4);
|
|
56
|
+
}
|
|
57
|
+
else if (e.key === 'ArrowUp') {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
y = Math.max(y - 1, 0);
|
|
60
|
+
}
|
|
61
|
+
else if (e.key === 'ArrowRight') {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
x = Math.min(x + 1, 4);
|
|
64
|
+
}
|
|
65
|
+
else if (e.key === 'ArrowLeft') {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
x = Math.max(0, x - 1);
|
|
68
|
+
}
|
|
69
|
+
boxes[y + x * 5].focus();
|
|
70
|
+
}
|
|
71
|
+
const positionText = {
|
|
72
|
+
0: {
|
|
73
|
+
0: 'Top Left Corner',
|
|
74
|
+
1: 'Upper Left',
|
|
75
|
+
2: 'Middle Left',
|
|
76
|
+
3: 'Lower Left',
|
|
77
|
+
4: 'Bottom Left Corner'
|
|
78
|
+
},
|
|
79
|
+
1: {
|
|
80
|
+
0: 'Top Left of Center',
|
|
81
|
+
1: 'Upper Left of Center',
|
|
82
|
+
2: 'Middle Left of Center',
|
|
83
|
+
3: 'Below Left of Center',
|
|
84
|
+
4: 'Bottom, Left of Center'
|
|
85
|
+
},
|
|
86
|
+
2: {
|
|
87
|
+
0: 'Top Center',
|
|
88
|
+
1: 'Upper Center',
|
|
89
|
+
2: 'Dead Center',
|
|
90
|
+
3: 'Below Center',
|
|
91
|
+
4: 'Bottom Center'
|
|
92
|
+
},
|
|
93
|
+
3: {
|
|
94
|
+
0: 'Top, Right of Center',
|
|
95
|
+
1: 'Upper Right of Center',
|
|
96
|
+
2: 'Middle Right of Center',
|
|
97
|
+
3: 'Below Right of Center',
|
|
98
|
+
4: 'Bottom, Right of Center'
|
|
99
|
+
},
|
|
100
|
+
4: {
|
|
101
|
+
0: 'Top Right Corner',
|
|
102
|
+
1: 'Upper Right',
|
|
103
|
+
2: 'Middle Right',
|
|
104
|
+
3: 'Lower Right',
|
|
105
|
+
4: 'Bottom Right Corner'
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
<FieldStandard bind:id {label} {path} {required} {defaultValue} conditional={conditional && isNotBlank(imageSrc)} {helptext} {descid} let:value let:setVal let:helptextid>
|
|
111
|
+
{@const _ = init(value)}
|
|
112
|
+
{#if isNotBlank(imageSrc)}
|
|
113
|
+
<Button icon={arrowsIn} on:click={showModal}>Adjust Image Position</Button>
|
|
114
|
+
{#if modalOpen}
|
|
115
|
+
<Dialog size="large" title={label} on:escape={hideModal} continueText="Save" cancelText="Cancel" on:continue={() => onSave(setVal)} {labelid}>
|
|
116
|
+
{#if info}
|
|
117
|
+
<section class="info">
|
|
118
|
+
{info}
|
|
119
|
+
</section>
|
|
120
|
+
<section class="position">
|
|
121
|
+
<p>
|
|
122
|
+
Using the grid overlays, select a focal point in your image to determine how Gato will align, position, and scale your image
|
|
123
|
+
in the section. This will help ensure the focal point of your image is always in frame. By default, Gato will
|
|
124
|
+
use the center of the image.
|
|
125
|
+
</p>
|
|
126
|
+
<div class="image-container">
|
|
127
|
+
<img class="crop-image" src={imageSrc} alt="" />
|
|
128
|
+
<div class="overlay" role="radiogroup" aria-labelledby={labelid}>
|
|
129
|
+
{#each Array.from(Array(5).keys()) as col}
|
|
130
|
+
{#each Array.from(Array(5).keys()) as row}
|
|
131
|
+
<div
|
|
132
|
+
bind:this={boxes[col + row * 5]}
|
|
133
|
+
class="box"
|
|
134
|
+
class:side={row === 4}
|
|
135
|
+
class:bottom={col === 4}
|
|
136
|
+
role="radio"
|
|
137
|
+
aria-checked={row === x && col === y}
|
|
138
|
+
tabindex={row === x && col === y ? 0 : -1}
|
|
139
|
+
on:click={() => onSelectBox(row, col)} on:keydown={onKeyDown}><ScreenReaderOnly>{positionText[row][col]}</ScreenReaderOnly></div>
|
|
140
|
+
{/each}
|
|
141
|
+
{/each}
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</section>
|
|
145
|
+
{/if}
|
|
146
|
+
</Dialog>
|
|
147
|
+
{/if}
|
|
148
|
+
{/if}
|
|
149
|
+
</FieldStandard>
|
|
150
|
+
|
|
151
|
+
<style>
|
|
152
|
+
section.position {
|
|
153
|
+
border: 1px dashed #767676;
|
|
154
|
+
padding: 1em;
|
|
155
|
+
display: flex;
|
|
156
|
+
flex-direction: column;
|
|
157
|
+
align-items: center;
|
|
158
|
+
}
|
|
159
|
+
.image-container {
|
|
160
|
+
width: 75%;
|
|
161
|
+
position: relative;
|
|
162
|
+
}
|
|
163
|
+
.crop-image {
|
|
164
|
+
width: 100%;
|
|
165
|
+
display: block;
|
|
166
|
+
}
|
|
167
|
+
.overlay {
|
|
168
|
+
position: absolute;
|
|
169
|
+
top: 0;
|
|
170
|
+
left: 0;
|
|
171
|
+
width: 100%;
|
|
172
|
+
height: 100%;
|
|
173
|
+
display: grid;
|
|
174
|
+
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
|
175
|
+
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
|
|
176
|
+
}
|
|
177
|
+
.overlay .box {
|
|
178
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
179
|
+
border-bottom: 1px dashed white;
|
|
180
|
+
border-right: 1px dashed white;
|
|
181
|
+
}
|
|
182
|
+
.overlay .box[aria-checked="true"] {
|
|
183
|
+
background-color: rgba(255, 255, 0, 0.5);
|
|
184
|
+
}
|
|
185
|
+
.overlay .box.side {
|
|
186
|
+
border-right-width: 0;
|
|
187
|
+
}
|
|
188
|
+
.overlay .box.bottom {
|
|
189
|
+
border-bottom-width: 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
</style>
|
|
193
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { type ImagePositionOutput } from '..';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
id?: string | undefined;
|
|
6
|
+
path: string;
|
|
7
|
+
imageSrc: string | undefined;
|
|
8
|
+
label?: string | undefined;
|
|
9
|
+
required?: boolean | undefined;
|
|
10
|
+
conditional?: boolean | undefined;
|
|
11
|
+
helptext?: string | undefined;
|
|
12
|
+
info?: string | undefined;
|
|
13
|
+
defaultValue?: ImagePositionOutput | undefined;
|
|
14
|
+
};
|
|
15
|
+
events: {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
};
|
|
18
|
+
slots: {};
|
|
19
|
+
};
|
|
20
|
+
export type FieldImagePositionProps = typeof __propDef.props;
|
|
21
|
+
export type FieldImagePositionEvents = typeof __propDef.events;
|
|
22
|
+
export type FieldImagePositionSlots = typeof __propDef.slots;
|
|
23
|
+
export default class FieldImagePosition extends SvelteComponentTyped<FieldImagePositionProps, FieldImagePositionEvents, FieldImagePositionSlots> {
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dosgato/dialog",
|
|
3
3
|
"description": "A component library for building forms that edit a JSON document.",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.21",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepublishOnly": "svelte-package",
|
|
7
7
|
"dev": "vite dev --force",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@iconify/svelte": "^3.1.6",
|
|
27
27
|
"@iconify-icons/mdi": "^1.2.22",
|
|
28
28
|
"@iconify-icons/ph": "^1.2.2",
|
|
29
|
-
"@txstate-mws/svelte-components": "^1.
|
|
29
|
+
"@txstate-mws/svelte-components": "^1.6.2",
|
|
30
30
|
"@txstate-mws/svelte-forms": "^1.4.2",
|
|
31
31
|
"codemirror": "^6.0.1",
|
|
32
32
|
"txstate-utils": "^1.8.0"
|