sol-components 2.1.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.
Files changed (150) hide show
  1. package/README.md +7 -0
  2. package/core/activate.js +27 -0
  3. package/core/adopt.js +71 -0
  4. package/core/auth-core.js +73 -0
  5. package/core/auth-fetch.js +154 -0
  6. package/core/component-mount.js +110 -0
  7. package/core/defaults.js +48 -0
  8. package/core/define.js +15 -0
  9. package/core/display-target.js +166 -0
  10. package/core/edit-placements.js +28 -0
  11. package/core/editor-self.js +127 -0
  12. package/core/editor.js +162 -0
  13. package/core/events.js +27 -0
  14. package/core/extension-points.js +189 -0
  15. package/core/form-utils.js +210 -0
  16. package/core/from-query.js +138 -0
  17. package/core/from-rdf.js +52 -0
  18. package/core/here.js +33 -0
  19. package/core/include-core.js +73 -0
  20. package/core/inrupt-global.js +18 -0
  21. package/core/menu-consumer.js +41 -0
  22. package/core/menu-rdf.js +154 -0
  23. package/core/pod-ops.js +392 -0
  24. package/core/pod-registry.js +82 -0
  25. package/core/popup-proxy.js +255 -0
  26. package/core/rdf-core.js +280 -0
  27. package/core/rdf-render.js +136 -0
  28. package/core/rdf-utils.js +411 -0
  29. package/core/rdf.js +154 -0
  30. package/core/services.js +106 -0
  31. package/core/shape-to-form.js +741 -0
  32. package/core/sparql-safety.js +20 -0
  33. package/core/utils.js +196 -0
  34. package/dist/importmap-cdn.json +49 -0
  35. package/dist/importmap-local.json +49 -0
  36. package/dist/sol-loader.manifest.json +140 -0
  37. package/dist/vendor/@comunica-query-sparql.js +137851 -0
  38. package/dist/vendor/@inrupt-solid-client-authn-browser.js +7503 -0
  39. package/dist/vendor/dompurify.js +1476 -0
  40. package/dist/vendor/ical.js.js +9739 -0
  41. package/dist/vendor/marked.js +85 -0
  42. package/dist/vendor/n3.js +14670 -0
  43. package/dist/vendor/rdf-validate-shacl.js +6970 -0
  44. package/dist/vendor/rdflib.js +35172 -0
  45. package/dist/vendor/solid-logic.js +6819 -0
  46. package/dist/vendor/solid-ui.js +21945 -0
  47. package/node/sol-form.js +133 -0
  48. package/node/sol-include.js +55 -0
  49. package/node/sol-login.js +632 -0
  50. package/node/sol-menu.js +639 -0
  51. package/node/sol-query.js +116 -0
  52. package/package.json +133 -0
  53. package/web/menu-from-rdf.js +23 -0
  54. package/web/scripts/prefs.js +25 -0
  55. package/web/sol-accordion.js +114 -0
  56. package/web/sol-basic.js +50 -0
  57. package/web/sol-breadcrumb.js +131 -0
  58. package/web/sol-button.js +244 -0
  59. package/web/sol-calendar.js +465 -0
  60. package/web/sol-default.js +118 -0
  61. package/web/sol-dropdown-button.js +222 -0
  62. package/web/sol-feed.js +1336 -0
  63. package/web/sol-form.js +949 -0
  64. package/web/sol-full.js +43 -0
  65. package/web/sol-gallery.js +303 -0
  66. package/web/sol-include.js +246 -0
  67. package/web/sol-live-edit.js +415 -0
  68. package/web/sol-login.js +856 -0
  69. package/web/sol-menu.js +593 -0
  70. package/web/sol-modal.js +377 -0
  71. package/web/sol-pod-extras.js +17 -0
  72. package/web/sol-pod-ops.js +680 -0
  73. package/web/sol-pod.js +1039 -0
  74. package/web/sol-query.js +546 -0
  75. package/web/sol-rolodex.js +95 -0
  76. package/web/sol-search.js +402 -0
  77. package/web/sol-settings.js +199 -0
  78. package/web/sol-solidos.js +93 -0
  79. package/web/sol-tabs.js +445 -0
  80. package/web/sol-time.js +194 -0
  81. package/web/sol-tree-edit.js +492 -0
  82. package/web/sol-wac.js +456 -0
  83. package/web/sol-weather.js +337 -0
  84. package/web/sol-window.js +142 -0
  85. package/web/styles/buttons-css.js +108 -0
  86. package/web/styles/help.css +242 -0
  87. package/web/styles/root.css +112 -0
  88. package/web/styles/sol-accordion-css.js +97 -0
  89. package/web/styles/sol-calendar-css.js +154 -0
  90. package/web/styles/sol-feed-css.js +475 -0
  91. package/web/styles/sol-form-css.js +471 -0
  92. package/web/styles/sol-gallery-css.js +181 -0
  93. package/web/styles/sol-include-css.js +95 -0
  94. package/web/styles/sol-live-edit-css.js +84 -0
  95. package/web/styles/sol-live-edit.css +101 -0
  96. package/web/styles/sol-login-css.js +116 -0
  97. package/web/styles/sol-menu-css.js +145 -0
  98. package/web/styles/sol-modal-css.js +134 -0
  99. package/web/styles/sol-pod-css.js +187 -0
  100. package/web/styles/sol-pod-modal-css.js +203 -0
  101. package/web/styles/sol-query-css.js +140 -0
  102. package/web/styles/sol-query-help.css +267 -0
  103. package/web/styles/sol-query-one-pager.css +67 -0
  104. package/web/styles/sol-search-css.js +157 -0
  105. package/web/styles/sol-solidos-css.js +7 -0
  106. package/web/styles/sol-tabs-css.js +114 -0
  107. package/web/styles/sol-time-css.js +30 -0
  108. package/web/styles/sol-wac-css.js +73 -0
  109. package/web/styles/sol-weather-css.js +59 -0
  110. package/web/styles/solid-logo.svg +9 -0
  111. package/web/styles/view-accordion-css.js +66 -0
  112. package/web/styles/view-anchorlist-css.js +22 -0
  113. package/web/styles/view-autocomplete-css.js +59 -0
  114. package/web/styles/view-rolodex-css.js +102 -0
  115. package/web/styles/view-select-css.js +21 -0
  116. package/web/utils/calendar-fetch.js +388 -0
  117. package/web/utils/code-mirror-editor.js +82 -0
  118. package/web/utils/commons-fetch.js +108 -0
  119. package/web/utils/feed-edit.js +159 -0
  120. package/web/utils/feed-edit.smoke.mjs +74 -0
  121. package/web/utils/feed-fetch.js +573 -0
  122. package/web/utils/live-edit-help/csv.js +64 -0
  123. package/web/utils/live-edit-help/graphviz.js +41 -0
  124. package/web/utils/live-edit-help/jsonld.js +55 -0
  125. package/web/utils/live-edit-help/markdown.js +52 -0
  126. package/web/utils/live-edit-help/mermaid.js +48 -0
  127. package/web/utils/live-edit-help/turtle.js +85 -0
  128. package/web/utils/rdf-config.js +125 -0
  129. package/web/utils/renderers/csv.js +124 -0
  130. package/web/utils/renderers/d3-force.js +82 -0
  131. package/web/utils/renderers/graphviz.js +13 -0
  132. package/web/utils/renderers/html.js +10 -0
  133. package/web/utils/renderers/jsonld.js +63 -0
  134. package/web/utils/renderers/markdown.js +19 -0
  135. package/web/utils/renderers/mermaid.js +54 -0
  136. package/web/utils/renderers/turtle.js +51 -0
  137. package/web/utils/sol-query-triple-patterns.js +151 -0
  138. package/web/utils/sol-query-ui.js +250 -0
  139. package/web/utils/sol-query-views.js +32 -0
  140. package/web/views/_helpers.js +34 -0
  141. package/web/views/accordion.js +133 -0
  142. package/web/views/anchorlist.js +59 -0
  143. package/web/views/auto-complete.js +183 -0
  144. package/web/views/dl.js +38 -0
  145. package/web/views/list.js +19 -0
  146. package/web/views/menu.js +56 -0
  147. package/web/views/rolodex.js +126 -0
  148. package/web/views/select.js +79 -0
  149. package/web/views/table.js +73 -0
  150. package/web/views/tabs.js +57 -0
@@ -0,0 +1,471 @@
1
+ import { sheetFrom } from '../../core/adopt.js';
2
+
3
+ export const CSS = `
4
+ :host {
5
+ display: flex;
6
+ flex-direction: column;
7
+ flex: 1;
8
+ min-height: 0;
9
+ font-family: var(--font-ui, system-ui, -apple-system, sans-serif);
10
+ box-sizing: border-box;
11
+ }
12
+
13
+ .sol-form-loading,
14
+ .sol-form-error {
15
+ padding: 1em;
16
+ }
17
+ .sol-form-error {
18
+ color: #c00;
19
+ white-space: pre-wrap;
20
+ }
21
+
22
+ /* ── form body rendered by solid-ui ── */
23
+ .sol-form-body {
24
+ flex: 1;
25
+ overflow: auto;
26
+ padding: 0.75em;
27
+ }
28
+ .sol-form-body input[type="text"],
29
+ .sol-form-body input[type="url"],
30
+ .sol-form-body select,
31
+ .sol-form-body textarea {
32
+ font-family: inherit;
33
+ font-size: 0.95em;
34
+ padding: 4px 6px;
35
+ border: 1px solid var(--border, #ccc);
36
+ border-radius: 3px;
37
+ box-sizing: border-box;
38
+ }
39
+ .sol-form-body input:focus,
40
+ .sol-form-body select:focus,
41
+ .sol-form-body textarea:focus {
42
+ outline: 2px solid var(--accent, #3b82f6);
43
+ outline-offset: -1px;
44
+ }
45
+
46
+ /* ── fallback form renderer ── */
47
+ .sf-group {
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 10px;
51
+ }
52
+ .sf-field {
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: 2px;
56
+ }
57
+ .sf-label {
58
+ font-weight: 500;
59
+ font-size: 0.9em;
60
+ color: var(--text-muted, #374151);
61
+ }
62
+ .sf-multiple {
63
+ border: 1px solid var(--border, #e0e0e0);
64
+ border-radius: 4px;
65
+ padding: 8px;
66
+ background: var(--bg-subtle, rgba(0,0,0,.02));
67
+ }
68
+ .sf-multiple .sf-multiple {
69
+ background: var(--bg-subtle2, rgba(0,0,0,.03));
70
+ }
71
+ .sf-multiple-header {
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: space-between;
75
+ margin-bottom: 8px;
76
+ }
77
+ .sf-multiple-list {
78
+ display: flex;
79
+ flex-direction: column;
80
+ gap: 8px;
81
+ }
82
+ .sf-multiple-item {
83
+ border: 1px solid var(--border, #d1d5db);
84
+ border-radius: 4px;
85
+ padding: 8px;
86
+ background: var(--bg, #fff);
87
+ }
88
+ .sf-item-actions {
89
+ display: flex;
90
+ gap: 4px;
91
+ justify-content: flex-end;
92
+ margin-bottom: 6px;
93
+ }
94
+ .sf-btn {
95
+ padding: 2px 8px;
96
+ border: 1px solid var(--border, #d1d5db);
97
+ border-radius: 3px;
98
+ background: var(--bg, #fff);
99
+ cursor: pointer;
100
+ font-size: 0.8em;
101
+ font-family: inherit;
102
+ }
103
+ .sf-btn:hover { background: var(--bg-hover, #f3f4f6); }
104
+ .sf-btn-add {
105
+ background: var(--accent, #3b82f6);
106
+ color: #fff;
107
+ border-color: var(--accent, #3b82f6);
108
+ padding: 3px 12px;
109
+ font-size: 0.85em;
110
+ }
111
+ .sf-btn-add:hover { background: var(--accent-hover, #2563eb); }
112
+ .sf-btn-remove {
113
+ color: #dc2626;
114
+ border-color: #fca5a5;
115
+ }
116
+ .sf-btn-remove:hover { background: #fef2f2; }
117
+ .sf-btn-move {
118
+ font-size: 0.75em;
119
+ padding: 2px 6px;
120
+ }
121
+ .sf-options { margin-top: 4px; }
122
+ .sf-depth-cap {
123
+ color: var(--text-muted, #6b7280);
124
+ font-style: italic;
125
+ font-size: 0.85em;
126
+ padding: 4px;
127
+ }
128
+
129
+ /* ── validation errors ── */
130
+ .sol-form-field-error {
131
+ color: #c00;
132
+ font-size: 0.85em;
133
+ margin-top: 2px;
134
+ }
135
+ .sol-form-validation-summary {
136
+ background: #fef2f2;
137
+ border: 1px solid #fca5a5;
138
+ border-radius: 4px;
139
+ padding: 0.5em 0.75em;
140
+ margin-bottom: 0.75em;
141
+ color: #991b1b;
142
+ font-size: 0.9em;
143
+ }
144
+ .sol-form-validation-summary ul {
145
+ margin: 0.25em 0 0 1.25em;
146
+ padding: 0;
147
+ }
148
+
149
+ /* ── save bar ── */
150
+ .sol-form-save-bar {
151
+ display: flex;
152
+ flex-direction: column;
153
+ gap: 8px;
154
+ padding: 0.75em;
155
+ border-top: 1px solid var(--border, #e0e0e0);
156
+ background: var(--bg-muted, #f9fafb);
157
+ }
158
+ .sol-form-save-options {
159
+ display: flex;
160
+ align-items: center;
161
+ gap: 12px;
162
+ font-size: 0.9em;
163
+ }
164
+ .sol-form-save-options label {
165
+ display: flex;
166
+ align-items: center;
167
+ gap: 4px;
168
+ cursor: pointer;
169
+ }
170
+ .sol-form-pod-url {
171
+ display: flex;
172
+ align-items: center;
173
+ gap: 6px;
174
+ }
175
+ .sol-form-pod-url input {
176
+ flex: 1;
177
+ font-family: inherit;
178
+ font-size: 0.9em;
179
+ padding: 4px 6px;
180
+ border: 1px solid var(--border, #ccc);
181
+ border-radius: 3px;
182
+ }
183
+ .sol-form-actions {
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 8px;
187
+ }
188
+ .sol-form-btn {
189
+ padding: 6px 16px;
190
+ border: none;
191
+ border-radius: 4px;
192
+ font-size: 0.9em;
193
+ cursor: pointer;
194
+ font-family: inherit;
195
+ }
196
+ .sol-form-btn-primary {
197
+ background: var(--accent, #3b82f6);
198
+ color: #fff;
199
+ }
200
+ .sol-form-btn-primary:hover {
201
+ background: var(--accent-hover, #2563eb);
202
+ }
203
+ .sol-form-btn-primary:disabled {
204
+ background: #9ca3af;
205
+ cursor: not-allowed;
206
+ }
207
+ .sol-form-save-status {
208
+ font-size: 0.85em;
209
+ margin-left: 8px;
210
+ }
211
+ .sol-form-save-status.ok { color: #16a34a; }
212
+ .sol-form-save-status.err { color: #c00; }
213
+
214
+ /* ── shape-driven mode ── */
215
+ .sol-form-shape-fields {
216
+ display: flex;
217
+ flex-direction: column;
218
+ gap: 0.9em;
219
+ }
220
+ .sol-form-shape-key {
221
+ display: grid;
222
+ grid-template-columns: minmax(10rem, 14rem) 1fr;
223
+ gap: 0.65em 1rem;
224
+ align-items: start;
225
+ }
226
+ .sol-form-shape-label {
227
+ padding-top: 0.4em;
228
+ font-weight: 600;
229
+ color: var(--text, #2c3e50);
230
+ user-select: none;
231
+ }
232
+ .sol-form-shape-rows {
233
+ display: flex;
234
+ flex-direction: column;
235
+ gap: 0.35em;
236
+ min-width: 0;
237
+ }
238
+ .sol-form-shape-row {
239
+ display: flex;
240
+ align-items: center;
241
+ gap: 0.4em;
242
+ min-width: 0;
243
+ }
244
+ .sol-form-shape-input {
245
+ flex: 1 1 auto;
246
+ min-width: 0;
247
+ font: inherit;
248
+ font-size: 0.95em;
249
+ padding: 0.45em 0.55em;
250
+ border: 1px solid var(--border, #d0d0d0);
251
+ border-radius: var(--radius-sm, 4px);
252
+ background: var(--surface, #fff);
253
+ color: var(--text, #000);
254
+ transition: border-color 120ms ease, box-shadow 120ms ease;
255
+ }
256
+ .sol-form-shape-input:focus-visible {
257
+ outline: none;
258
+ border-color: var(--accent, #1F618D);
259
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #1F618D) 22%, transparent);
260
+ }
261
+ /* In rolodex mode each card holds one record's worth of fields; let
262
+ inputs fill the card width so long values (URLs, etc.) aren't
263
+ clipped to the browser default ~150px size. */
264
+ .sol-form-rolodex-page input[type="text"],
265
+ .sol-form-rolodex-page input[type="url"],
266
+ .sol-form-rolodex-page input[type="email"],
267
+ .sol-form-rolodex-page textarea {
268
+ width: 100%;
269
+ box-sizing: border-box;
270
+ }
271
+ .sol-form-shape-input[type="checkbox"] {
272
+ flex: 0 0 auto;
273
+ width: 1.1em;
274
+ height: 1.1em;
275
+ padding: 0;
276
+ }
277
+ .sol-form-shape-add,
278
+ .sol-form-shape-remove {
279
+ grid-column: 2;
280
+ align-self: start;
281
+ font: inherit;
282
+ font-size: 0.85em;
283
+ padding: 0.25em 0.6em;
284
+ border: 1px solid var(--border, #d0d0d0);
285
+ background: var(--surface, #fff);
286
+ color: var(--text-muted, #4d4d4d);
287
+ border-radius: var(--radius-sm, 4px);
288
+ cursor: pointer;
289
+ }
290
+ .sol-form-shape-add:hover {
291
+ border-color: var(--accent, #1F618D);
292
+ color: var(--accent, #1F618D);
293
+ }
294
+ .sol-form-shape-remove {
295
+ flex: 0 0 auto;
296
+ width: 1.8em;
297
+ padding: 0;
298
+ line-height: 1;
299
+ color: var(--error, #c00);
300
+ border-color: color-mix(in srgb, var(--error, #c00) 35%, var(--border, #d0d0d0));
301
+ }
302
+ .sol-form-shape-remove:hover {
303
+ background: color-mix(in srgb, var(--error, #c00) 10%, transparent);
304
+ }
305
+
306
+ /* Lay the whole shape-driven form out as a grid so labels line up
307
+ in a column across every field, regardless of which solid-ui
308
+ widget renders the row. Each row container uses display:contents
309
+ so the widget's emitted label + input become direct grid items. */
310
+ .sol-form-shape-fields {
311
+ display: grid;
312
+ grid-template-columns: minmax(8rem, max-content) 1fr;
313
+ column-gap: 1rem;
314
+ row-gap: 0.5rem;
315
+ align-items: baseline;
316
+ width: 100%;
317
+ }
318
+ .sol-form-shape-fields > .sol-form-shape-key {
319
+ display: contents;
320
+ }
321
+ /* solid-ui wraps text fields in an unclassed inline-styled
322
+ div (display:flex flex-direction:row). Without this override the
323
+ wrapper becomes a single grid cell and labels stop lining up
324
+ between text-field rows and Choice/Multiple rows. !important is
325
+ required to beat solid-ui's inline style. */
326
+ .sol-form-shape-fields > .sol-form-shape-key > div {
327
+ display: contents !important;
328
+ }
329
+ /* solid-ui's labels: formFieldName for field types, choiceBox-label
330
+ for Choice. Force right-align + first column. */
331
+ .sol-form-shape-fields .formFieldName,
332
+ .sol-form-shape-fields .choiceBox-label {
333
+ grid-column: 1;
334
+ justify-self: end;
335
+ text-align: right;
336
+ color: var(--accent, #1F618D);
337
+ font-weight: 500;
338
+ padding-top: 0.4em;
339
+ }
340
+ /* solid-ui's value containers: formFieldValue for fields, choiceBox-
341
+ selectBox for Choice. Take the input column and stretch. */
342
+ .sol-form-shape-fields .formFieldValue,
343
+ .sol-form-shape-fields .choiceBox-selectBox {
344
+ grid-column: 2;
345
+ justify-self: stretch;
346
+ min-width: 0;
347
+ }
348
+ /* solid-ui paints inline styling on every input/select it emits
349
+ (light-blue background, custom border + radius, 0.4em margin).
350
+ Re-skin to match dk's chrome controls so the dropdown does not
351
+ look out-of-place next to the text inputs. !important is needed
352
+ to beat solid-ui's inline styles. */
353
+ .sol-form-shape-fields .formFieldValue > input,
354
+ .sol-form-shape-fields .formFieldValue > select,
355
+ .sol-form-shape-fields .formFieldValue > textarea,
356
+ .sol-form-shape-fields .choiceBox-selectBox select {
357
+ width: 100%;
358
+ max-width: 28rem;
359
+ box-sizing: border-box;
360
+ background: var(--surface, #fff) !important;
361
+ color: var(--text, #000) !important;
362
+ border: 1px solid var(--border, #9e9e9e) !important;
363
+ border-radius: var(--radius-sm, 4px) !important;
364
+ padding: 0.35em 0.6em !important;
365
+ margin: 0 !important;
366
+ font: inherit !important;
367
+ }
368
+ .sol-form-shape-fields .formFieldValue > input:focus-visible,
369
+ .sol-form-shape-fields .formFieldValue > select:focus-visible,
370
+ .sol-form-shape-fields .formFieldValue > textarea:focus-visible,
371
+ .sol-form-shape-fields .choiceBox-selectBox select:focus-visible {
372
+ outline: 2px solid var(--accent, #1F618D) !important;
373
+ outline-offset: 1px !important;
374
+ border-color: var(--accent, #1F618D) !important;
375
+ }
376
+ /* solid-ui's Multiple emits a wrapping container with each item as a
377
+ row; align its label too. */
378
+ .sol-form-shape-fields .choiceBox {
379
+ display: contents;
380
+ }
381
+
382
+ /* Multi-valued primitive rows (workaround for solid-ui basicField in
383
+ Multiple). Label takes column 1, the value box (list of inputs +
384
+ add button) takes column 2. */
385
+ .sol-form-shape-multi-label {
386
+ grid-column: 1;
387
+ justify-self: end;
388
+ text-align: right;
389
+ color: var(--accent, #1F618D);
390
+ font-weight: 500;
391
+ padding-top: 0.4em;
392
+ }
393
+ .sol-form-shape-multi-value {
394
+ grid-column: 2;
395
+ justify-self: stretch;
396
+ min-width: 0;
397
+ display: flex;
398
+ flex-direction: column;
399
+ gap: 0.3em;
400
+ }
401
+ .sol-form-shape-multi-list {
402
+ display: flex;
403
+ flex-direction: column;
404
+ gap: 0.3em;
405
+ }
406
+ .sol-form-shape-multi-item {
407
+ display: flex;
408
+ gap: 0.4em;
409
+ align-items: center;
410
+ }
411
+ .sol-form-shape-multi-item > input {
412
+ flex: 1;
413
+ max-width: 28rem;
414
+ box-sizing: border-box;
415
+ background: var(--surface, #fff);
416
+ color: var(--text, #000);
417
+ border: 1px solid var(--border, #9e9e9e);
418
+ border-radius: var(--radius-sm, 4px);
419
+ padding: 0.35em 0.6em;
420
+ font: inherit;
421
+ }
422
+ .sol-form-shape-multi-item > input:focus-visible {
423
+ outline: 2px solid var(--accent, #1F618D);
424
+ outline-offset: 1px;
425
+ border-color: var(--accent, #1F618D);
426
+ }
427
+ .sol-form-shape-multi-del {
428
+ background: transparent;
429
+ border: 1px solid var(--border, #9e9e9e);
430
+ border-radius: var(--radius-sm, 4px);
431
+ padding: 0.2em 0.5em;
432
+ color: var(--text-muted, #666);
433
+ cursor: pointer;
434
+ }
435
+ .sol-form-shape-multi-del:hover {
436
+ color: var(--text, #000);
437
+ }
438
+ .sol-form-shape-multi-add {
439
+ align-self: start;
440
+ background: transparent;
441
+ border: 1px dashed var(--border, #9e9e9e);
442
+ border-radius: var(--radius-sm, 4px);
443
+ padding: 0.25em 0.65em;
444
+ color: var(--accent, #1F618D);
445
+ cursor: pointer;
446
+ font: inherit;
447
+ }
448
+ .sol-form-shape-multi-add:hover {
449
+ background: var(--focus-bg, #e3f2fd);
450
+ }
451
+
452
+ /* Read-only ("no-edit") mode: inputs render but the user can't
453
+ change them. Light cosmetic shift to telegraph the mode. */
454
+ .sol-form-shape-readonly .sol-form-shape-input[readonly],
455
+ .sol-form-shape-readonly .sol-form-shape-input:disabled {
456
+ background: color-mix(in srgb, var(--surface, #fff) 90%, var(--border, #d0d0d0));
457
+ color: var(--text-muted, #4d4d4d);
458
+ cursor: default;
459
+ }
460
+ .sol-form-shape-readonly .sol-form-shape-input[readonly]:focus-visible,
461
+ .sol-form-shape-readonly .sol-form-shape-input:disabled:focus-visible {
462
+ outline: 1px dashed var(--border, #d0d0d0);
463
+ box-shadow: none;
464
+ }
465
+ .sol-form-shape-empty {
466
+ color: var(--text-muted, #4d4d4d);
467
+ font-style: italic;
468
+ }
469
+ `;
470
+
471
+ export const sheet = sheetFrom(CSS);
@@ -0,0 +1,181 @@
1
+ // Styles for <sol-gallery>'s shadow root. Exports the raw `CSS` string plus a
2
+ // constructable `sheet`, matching the other web/styles/*-css.js modules. All
3
+ // colours / metrics reference the shared design tokens so the component themes
4
+ // with the rest of the suite (see <sol-feed>'s css for the token set).
5
+ import { sheetFrom } from '../../core/adopt.js';
6
+
7
+ export const CSS = `
8
+ :host {
9
+ display: flex;
10
+ flex-direction: column;
11
+ height: 100%;
12
+ max-height: 100vh;
13
+ min-height: 0;
14
+ font-family: var(--font-ui, system-ui, -apple-system, sans-serif);
15
+ font-size: var(--font-size, 20px);
16
+ color: var(--text, #212121);
17
+ background: var(--bg, #f5f5f5);
18
+ }
19
+ * { box-sizing: border-box; }
20
+
21
+ /* The scroll container for the masonry grid (also the paging root). The
22
+ host owns any topic/collection selectors — the gallery is display-only. */
23
+ .gallery-main {
24
+ flex: 1 1 auto;
25
+ min-width: 0;
26
+ min-height: 0;
27
+ overflow: auto;
28
+ display: flex;
29
+ flex-direction: column;
30
+ }
31
+ .gallery-status {
32
+ flex: 0 0 auto;
33
+ padding: .2rem 1rem .6rem;
34
+ font-size: .78em;
35
+ color: var(--text-muted, #7f8c8d);
36
+ }
37
+ .gallery-status[data-error] { color: var(--error, #e74c3c); }
38
+ .gallery-empty {
39
+ margin: auto;
40
+ padding: 2rem;
41
+ color: var(--text-muted, #7f8c8d);
42
+ font-style: italic;
43
+ text-align: center;
44
+ }
45
+
46
+ /* Masonry via CSS multicol — varying-height thumbs flow into columns. */
47
+ .gallery-grid {
48
+ flex: 1 1 auto;
49
+ columns: 220px;
50
+ column-gap: .7rem;
51
+ padding: 0 1rem 1rem;
52
+ }
53
+ .gallery-thumb {
54
+ break-inside: avoid;
55
+ margin: 0 0 .7rem;
56
+ padding: 0;
57
+ border: none;
58
+ width: 100%;
59
+ display: block;
60
+ background: var(--surface, #fff);
61
+ border-radius: 8px;
62
+ overflow: hidden;
63
+ cursor: pointer;
64
+ box-shadow: 0 1px 4px var(--shadow, rgba(0,0,0,0.08));
65
+ }
66
+ .gallery-thumb img {
67
+ width: 100%;
68
+ height: auto;
69
+ display: block;
70
+ background: color-mix(in srgb, var(--bg, #ccc) 70%, #000);
71
+ }
72
+ .gallery-thumb:hover { box-shadow: 0 3px 12px var(--shadow, rgba(0,0,0,0.22)); }
73
+ .gallery-thumb:focus-visible { outline: 2px solid var(--accent, #3498db); outline-offset: 2px; }
74
+
75
+ .gallery-sentinel { height: 1px; }
76
+ .gallery-more {
77
+ flex: 0 0 auto;
78
+ align-self: center;
79
+ margin: .2rem auto 1rem;
80
+ font: inherit;
81
+ font-size: .8em;
82
+ padding: .35rem 1.1rem;
83
+ border: 1px solid var(--border, #d0d0d0);
84
+ border-radius: 999px;
85
+ background: var(--surface, #fff);
86
+ color: var(--text, #212121);
87
+ cursor: pointer;
88
+ }
89
+ .gallery-more:hover { background: var(--hover, #eaf2fb); }
90
+
91
+ /* ── lightbox overlay ────────────────────────────────────────────────── */
92
+ .gallery-lightbox {
93
+ position: fixed;
94
+ inset: 0;
95
+ z-index: 1000;
96
+ display: flex;
97
+ flex-direction: column;
98
+ align-items: center;
99
+ justify-content: center;
100
+ background: rgba(0,0,0,.86);
101
+ padding: 2.5rem 4rem;
102
+ }
103
+ .gallery-lightbox[hidden] { display: none; }
104
+ .gallery-lightbox img {
105
+ max-width: 100%;
106
+ max-height: calc(100% - 3rem);
107
+ object-fit: contain;
108
+ border-radius: 4px;
109
+ box-shadow: 0 8px 40px rgba(0,0,0,.6);
110
+ cursor: zoom-in;
111
+ }
112
+ /* Image already shown at full resolution — no zoom affordance. */
113
+ .gallery-lightbox.no-zoom img { cursor: default; }
114
+
115
+ /* Actual-size (100%) view: full-bleed, natural pixels, scroll to pan. */
116
+ .gallery-lightbox.zoomed {
117
+ padding: 0;
118
+ display: block; /* a block scroll container, not the flex box */
119
+ overflow: auto;
120
+ }
121
+ .gallery-lightbox.zoomed img {
122
+ max-width: none;
123
+ max-height: none;
124
+ width: auto;
125
+ height: auto;
126
+ object-fit: none;
127
+ border-radius: 0;
128
+ margin: auto; /* centre when smaller than the viewport */
129
+ cursor: zoom-out;
130
+ }
131
+ .gallery-lightbox.zoomed .gallery-lb-caption,
132
+ .gallery-lightbox.zoomed .gallery-lb-prev,
133
+ .gallery-lightbox.zoomed .gallery-lb-next { display: none; }
134
+ /* Keep Close reachable while the overlay scrolls. */
135
+ .gallery-lightbox.zoomed .gallery-lb-close { position: fixed; z-index: 1001; }
136
+ .gallery-lb-caption {
137
+ margin-top: .8rem;
138
+ max-width: 60rem;
139
+ text-align: center;
140
+ color: #f0f0f0;
141
+ font-size: .8em;
142
+ line-height: 1.4;
143
+ }
144
+ .gallery-lb-caption a { color: #9cd0ff; }
145
+ .gallery-lb-btn {
146
+ position: absolute;
147
+ top: 50%;
148
+ transform: translateY(-50%);
149
+ font-size: 2.2rem;
150
+ line-height: 1;
151
+ width: 3rem;
152
+ height: 4rem;
153
+ border: none;
154
+ border-radius: 8px;
155
+ background: rgba(255,255,255,.1);
156
+ color: #fff;
157
+ cursor: pointer;
158
+ }
159
+ .gallery-lb-btn:hover { background: rgba(255,255,255,.22); }
160
+ .gallery-lb-prev { left: .6rem; }
161
+ .gallery-lb-next { right: .6rem; }
162
+ .gallery-lb-close {
163
+ position: absolute;
164
+ top: .6rem;
165
+ right: .8rem;
166
+ font-size: 1.6rem;
167
+ line-height: 1;
168
+ width: 2.4rem;
169
+ height: 2.4rem;
170
+ border: none;
171
+ border-radius: 8px;
172
+ background: rgba(255,255,255,.1);
173
+ color: #fff;
174
+ cursor: pointer;
175
+ }
176
+ .gallery-lb-close:hover { background: rgba(255,255,255,.22); }
177
+ .gallery-lb-btn:focus-visible,
178
+ .gallery-lb-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
179
+ `;
180
+
181
+ export const sheet = sheetFrom(CSS);