@dosgato/dialog 1.1.20 → 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.
@@ -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} id={helptextid} class="dialog-field-help" class:needsShowHelp class:expanded={showhelp} on:click={() => { if (needsShowHelp) showhelp = !showhelp }}>
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}
@@ -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)
@@ -122,7 +122,7 @@ async function reactToAspectRatio(ar) {
122
122
  store.updateTargetAspect(ar);
123
123
  await tick();
124
124
  if (ar !== initialAspectRatio || arChanged) {
125
- store.reset();
125
+ store.maximize();
126
126
  arChanged = true;
127
127
  }
128
128
  }
@@ -234,23 +234,38 @@ 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
  }
252
267
 
253
- .icon-picker-item[aria-checked=true] :global(svg) {
268
+ .icon-picker-item[aria-checked=true] {
254
269
  outline: 4px solid #93BBC4;
255
270
  background-color: #eee;
256
271
  }
@@ -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,2 @@
1
+ export { default as FieldImagePosition } from './FieldImagePosition.svelte';
2
+ export * from './position.js';
@@ -0,0 +1,2 @@
1
+ export { default as FieldImagePosition } from './FieldImagePosition.svelte';
2
+ export * from './position.js';
@@ -0,0 +1,4 @@
1
+ export interface ImagePositionOutput {
2
+ x: number;
3
+ y: number;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -42,3 +42,4 @@ export * from './helpers.js';
42
42
  export * from './tree/index.js';
43
43
  export * from './cropper/index.js';
44
44
  export * from './code/index.js';
45
+ export * from './imageposition/index.js';
package/dist/index.js CHANGED
@@ -42,3 +42,4 @@ export * from './helpers.js';
42
42
  export * from './tree/index.js';
43
43
  export * from './cropper/index.js';
44
44
  export * from './code/index.js';
45
+ export * from './imageposition/index.js';
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.20",
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.5.5",
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"