@cardinali-studio/adminkit 1.0.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/dist/api.d.ts +195 -0
- package/dist/api.js +118 -0
- package/dist/app/App.d.ts +3 -0
- package/dist/app/App.js +320 -0
- package/dist/app/app.css +2068 -0
- package/dist/app/index.d.ts +18 -0
- package/dist/app/index.js +33 -0
- package/dist/app/lib/bookings.d.ts +132 -0
- package/dist/app/lib/bookings.js +79 -0
- package/dist/app/lib/deliveries.d.ts +95 -0
- package/dist/app/lib/deliveries.js +104 -0
- package/dist/app/lib/delivery-drop.d.ts +1 -0
- package/dist/app/lib/delivery-drop.js +72 -0
- package/dist/app/lib/delivery-upload.d.ts +78 -0
- package/dist/app/lib/delivery-upload.js +585 -0
- package/dist/app/lib/groups.d.ts +9 -0
- package/dist/app/lib/groups.js +32 -0
- package/dist/app/lib/home.d.ts +11 -0
- package/dist/app/lib/home.js +67 -0
- package/dist/app/lib/overview.d.ts +82 -0
- package/dist/app/lib/overview.js +68 -0
- package/dist/app/lib/pages.d.ts +24 -0
- package/dist/app/lib/pages.js +156 -0
- package/dist/app/lib/publish.d.ts +18 -0
- package/dist/app/lib/publish.js +63 -0
- package/dist/app/lib/reorder.d.ts +3 -0
- package/dist/app/lib/reorder.js +31 -0
- package/dist/app/lib/requests.d.ts +10 -0
- package/dist/app/lib/requests.js +67 -0
- package/dist/app/lib/router.d.ts +1 -0
- package/dist/app/lib/router.js +14 -0
- package/dist/app/lib/settings.d.ts +29 -0
- package/dist/app/lib/settings.js +82 -0
- package/dist/app/lib/slug.d.ts +3 -0
- package/dist/app/lib/slug.js +23 -0
- package/dist/app/lib/text.d.ts +1 -0
- package/dist/app/lib/text.js +13 -0
- package/dist/app/lib/theme.d.ts +7 -0
- package/dist/app/lib/theme.js +43 -0
- package/dist/app/lib/upload-queue.d.ts +35 -0
- package/dist/app/lib/upload-queue.js +167 -0
- package/dist/app/routes/AboutEditor.d.ts +15 -0
- package/dist/app/routes/AboutEditor.js +122 -0
- package/dist/app/routes/Bookings.d.ts +21 -0
- package/dist/app/routes/Bookings.js +134 -0
- package/dist/app/routes/Deliveries.d.ts +37 -0
- package/dist/app/routes/Deliveries.js +563 -0
- package/dist/app/routes/GallerySectionsEditor.d.ts +12 -0
- package/dist/app/routes/GallerySectionsEditor.js +107 -0
- package/dist/app/routes/HomeEditor.d.ts +10 -0
- package/dist/app/routes/HomeEditor.js +188 -0
- package/dist/app/routes/Overview.d.ts +17 -0
- package/dist/app/routes/Overview.js +318 -0
- package/dist/app/routes/PageActions.d.ts +12 -0
- package/dist/app/routes/PageActions.js +93 -0
- package/dist/app/routes/PageEditor.d.ts +23 -0
- package/dist/app/routes/PageEditor.js +233 -0
- package/dist/app/routes/PageSeoEditor.d.ts +13 -0
- package/dist/app/routes/PageSeoEditor.js +102 -0
- package/dist/app/routes/PagesList.d.ts +10 -0
- package/dist/app/routes/PagesList.js +76 -0
- package/dist/app/routes/PortfolioWorksEditor.d.ts +12 -0
- package/dist/app/routes/PortfolioWorksEditor.js +139 -0
- package/dist/app/routes/Requests.d.ts +13 -0
- package/dist/app/routes/Requests.js +30 -0
- package/dist/app/routes/SiteSettingsEditor.d.ts +21 -0
- package/dist/app/routes/SiteSettingsEditor.js +66 -0
- package/dist/app/routes/UploadDock.d.ts +1 -0
- package/dist/app/routes/UploadDock.js +66 -0
- package/dist/app/routes/WorkshopEditionsEditor.d.ts +12 -0
- package/dist/app/routes/WorkshopEditionsEditor.js +101 -0
- package/dist/app/site.d.ts +37 -0
- package/dist/app/site.js +18 -0
- package/dist/app/ui/MediaSlot.d.ts +10 -0
- package/dist/app/ui/MediaSlot.js +20 -0
- package/dist/app/ui/OpenCard.d.ts +18 -0
- package/dist/app/ui/OpenCard.js +20 -0
- package/dist/app/ui/ParagraphEditor.d.ts +8 -0
- package/dist/app/ui/ParagraphEditor.js +37 -0
- package/dist/app/ui/dnd.d.ts +1 -0
- package/dist/app/ui/dnd.js +11 -0
- package/dist/app/ui/icons.d.ts +26 -0
- package/dist/app/ui/icons.js +45 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +26 -0
- package/dist/form/MediaBrowser.d.ts +13 -0
- package/dist/form/MediaBrowser.js +24 -0
- package/dist/form/MediaPicker.d.ts +10 -0
- package/dist/form/MediaPicker.js +20 -0
- package/dist/form/SchemaForm.d.ts +21 -0
- package/dist/form/SchemaForm.js +67 -0
- package/dist/form/Trash.d.ts +1 -0
- package/dist/form/Trash.js +42 -0
- package/dist/form/fields/index.d.ts +1 -0
- package/dist/form/fields/index.js +110 -0
- package/dist/form/fields/objectList.d.ts +1 -0
- package/dist/form/fields/objectList.js +99 -0
- package/dist/form/index.d.ts +8 -0
- package/dist/form/index.js +8 -0
- package/dist/form/media/Lightbox.d.ts +4 -0
- package/dist/form/media/Lightbox.js +70 -0
- package/dist/form/media/MediaFolders.d.ts +20 -0
- package/dist/form/media/MediaFolders.js +116 -0
- package/dist/form/media/MediaGrid.d.ts +8 -0
- package/dist/form/media/MediaGrid.js +139 -0
- package/dist/form/media/UploadDialog.d.ts +4 -0
- package/dist/form/media/UploadDialog.js +37 -0
- package/dist/form/media/useMediaLibrary.d.ts +55 -0
- package/dist/form/media/useMediaLibrary.js +495 -0
- package/dist/form/prose/ProseBar.d.ts +21 -0
- package/dist/form/prose/ProseBar.js +111 -0
- package/dist/form/prose/ProseField.d.ts +11 -0
- package/dist/form/prose/ProseField.js +152 -0
- package/dist/form/prose/pages.d.ts +6 -0
- package/dist/form/prose/pages.js +13 -0
- package/dist/form/registry.d.ts +20 -0
- package/dist/form/registry.js +15 -0
- package/dist/frontmatter.d.ts +20 -0
- package/dist/frontmatter.js +202 -0
- package/dist/functions/_middleware.js +101 -0
- package/dist/functions/_shared/analytics-ga4.js +248 -0
- package/dist/functions/_shared/analytics-umami.js +119 -0
- package/dist/functions/_shared/assets.js +90 -0
- package/dist/functions/_shared/b2.js +300 -0
- package/dist/functions/_shared/delivery-crypto.js +99 -0
- package/dist/functions/_shared/delivery-purge.js +222 -0
- package/dist/functions/_shared/edge-cache.js +37 -0
- package/dist/functions/_shared/exif.js +53 -0
- package/dist/functions/_shared/github.js +138 -0
- package/dist/functions/_shared/imagesize.js +101 -0
- package/dist/functions/_shared/media-content.js +200 -0
- package/dist/functions/_shared/pending-media.js +98 -0
- package/dist/functions/_shared/refs.js +155 -0
- package/dist/functions/api/analytics.js +106 -0
- package/dist/functions/api/assets/delete.js +241 -0
- package/dist/functions/api/assets/folder.js +43 -0
- package/dist/functions/api/assets/folders.js +32 -0
- package/dist/functions/api/assets/move.js +253 -0
- package/dist/functions/api/assets/preview.js +17 -0
- package/dist/functions/api/assets/trash/delete.js +13 -0
- package/dist/functions/api/assets/trash/empty.js +16 -0
- package/dist/functions/api/assets/trash/restore.js +43 -0
- package/dist/functions/api/assets/trash.js +28 -0
- package/dist/functions/api/assets/upload.js +54 -0
- package/dist/functions/api/assets/usage.js +41 -0
- package/dist/functions/api/assets.js +94 -0
- package/dist/functions/api/deliveries.js +629 -0
- package/dist/functions/api/delivery/hero.js +21 -0
- package/dist/functions/api/delivery/image.js +35 -0
- package/dist/functions/api/delivery/multipart.js +261 -0
- package/dist/functions/api/pages/get.js +26 -0
- package/dist/functions/api/pages.js +354 -0
- package/dist/functions/api/publish.js +134 -0
- package/dist/functions/api/requests.js +57 -0
- package/dist/functions/api/settings.js +236 -0
- package/dist/functions/api/singleton.js +105 -0
- package/dist/functions/api/storage.js +125 -0
- package/dist/functions/index.js +124 -0
- package/dist/functions/site.js +38 -0
- package/dist/gallery.d.ts +28 -0
- package/dist/gallery.js +18 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/model.d.ts +2 -0
- package/dist/model.js +47 -0
- package/dist/normalize.d.ts +50 -0
- package/dist/normalize.js +120 -0
- package/dist/preview.d.ts +3 -0
- package/dist/preview.js +82 -0
- package/dist/prose.d.ts +17 -0
- package/dist/prose.js +205 -0
- package/dist/registries.d.ts +43 -0
- package/dist/registries.js +29 -0
- package/dist/serialize.d.ts +26 -0
- package/dist/serialize.js +136 -0
- package/dist/testing.d.ts +26 -0
- package/dist/testing.js +66 -0
- package/dist/theme.css +636 -0
- package/dist/yaml.d.ts +8 -0
- package/dist/yaml.js +90 -0
- package/package.json +97 -0
package/dist/theme.css
ADDED
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
/* Tema dell'admin — SOLE custom property e le regole che le usano.
|
|
2
|
+
*
|
|
3
|
+
* Questi sono i **default del motore**, non l'aspetto di un cliente. Il sito che monta il kit
|
|
4
|
+
* li sovrascrive nel suo `admin/src/theme.css`, che viene importato DOPO: i default restano
|
|
5
|
+
* qui perché il kit deve funzionare da solo, e una variabile che un cliente non ridefinisce
|
|
6
|
+
* non deve dare un pannello rotto senza nessun errore.
|
|
7
|
+
*
|
|
8
|
+
* La regola che tiene in piedi la separazione: se una richiesta di aspetto non si può esprimere
|
|
9
|
+
* ridefinendo una variabile, la risposta giusta NON è modificare un componente qui dentro — è
|
|
10
|
+
* aggiungere una variabile, così la ottengono tutti i siti. Un componente modificato per un
|
|
11
|
+
* cliente è il primo passo verso un fork del motore.
|
|
12
|
+
*
|
|
13
|
+
* Le classi sono prefissate `ak-` per non incrociare né site.css né il vecchio admin.css.
|
|
14
|
+
*
|
|
15
|
+
* NB: questo file si consuma da `dist/` (l'export del pacchetto è `"./theme.css":
|
|
16
|
+
* "./dist/theme.css"`, la copia la fa `npm run build` di adminkit), quindi dopo averlo toccato
|
|
17
|
+
* serve `npm run build:pkgs`. Il `theme.css` del cliente invece lo compila Vite insieme
|
|
18
|
+
* all'admin: i due file si comportano diversamente, ed è già costata una modifica che sembrava
|
|
19
|
+
* non avere effetto.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
:root {
|
|
23
|
+
color-scheme: light;
|
|
24
|
+
--ak-bg: #fbfbfa;
|
|
25
|
+
--ak-panel: #ffffff;
|
|
26
|
+
--ak-ink: #1a1a1a;
|
|
27
|
+
--ak-ink-quiet: #6b6b6b;
|
|
28
|
+
--ak-line: #e4e4e2;
|
|
29
|
+
--ak-accent: #b94732;
|
|
30
|
+
--ak-accent-ink: #ffffff;
|
|
31
|
+
--ak-accent-hover: #a33d2a;
|
|
32
|
+
--ak-danger: #b00020;
|
|
33
|
+
--ak-radius: 6px;
|
|
34
|
+
--ak-gap: 14px;
|
|
35
|
+
--ak-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
|
36
|
+
|
|
37
|
+
/* Il guscio a tre colonne. Stanno qui e non nell'app perché sono la leva con cui un altro
|
|
38
|
+
sito cambia pelle senza toccare un componente: la colonna scura, la sua larghezza, il grigio
|
|
39
|
+
dell'elenco. */
|
|
40
|
+
--ak-rail-w: 208px;
|
|
41
|
+
--ak-col-w: 272px;
|
|
42
|
+
--ak-rail-bg: #17181a;
|
|
43
|
+
--ak-rail-ink: #9b9b98;
|
|
44
|
+
--ak-rail-ink-on: #ffffff;
|
|
45
|
+
--ak-rail-hover: rgba(255, 255, 255, .06);
|
|
46
|
+
--ak-rail-on: rgba(255, 255, 255, .11);
|
|
47
|
+
--ak-rail-line: rgba(255, 255, 255, .10);
|
|
48
|
+
--ak-col-bg: #f4f4f2;
|
|
49
|
+
/* Due nomi usati da tempo in `.bk-*` (Prenotazioni) sempre con un fallback hardcoded
|
|
50
|
+
(`var(--ak-muted,#777)`, `var(--ak-paper,#fff)`), perché non erano mai stati dichiarati
|
|
51
|
+
davvero: senza una vera custom property qui, quel fallback è tutto ciò che Prenotazioni
|
|
52
|
+
vedrà mai, tema scuro compreso. Sono alias, non nuovi concetti — non aggiungono un quinto
|
|
53
|
+
piano alla gerarchia delle superfici, si limitano a dare un nome che `.bk-*` già usa a due
|
|
54
|
+
token che esistono già. */
|
|
55
|
+
--ak-muted: var(--ak-ink-quiet);
|
|
56
|
+
--ak-paper: var(--ak-panel);
|
|
57
|
+
/* Fra `--ak-ink-quiet` e `--ak-line`: usata da alcune regole (`.dl-state`, `.dl-total`,
|
|
58
|
+
`.ov-stat-quiet`) da prima che fosse mai dichiarata — con la sola varianti col fallback
|
|
59
|
+
`var(--ak-ink-faint, var(--ak-ink-quiet))` funzionavano per caso, le altre restavano senza
|
|
60
|
+
valore. */
|
|
61
|
+
--ak-ink-faint: #9a9a94;
|
|
62
|
+
/* Lato della cella nella griglia dei media: cambia quante foto entrano per riga. */
|
|
63
|
+
--ak-cell: 152px;
|
|
64
|
+
/* Il passaggio del mouse è un velo, la SELEZIONE è un pannello bianco con la sua barra
|
|
65
|
+
d'accento: se i due stati si somigliano, l'elenco smette di dire dove sei. */
|
|
66
|
+
--ak-hover: rgba(0, 0, 0, .045);
|
|
67
|
+
--ak-font: ui-sans-serif, system-ui, -apple-system, "Helvetica Neue", sans-serif;
|
|
68
|
+
--ak-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
69
|
+
--ak-fs: 14px;
|
|
70
|
+
--ak-fs-small: 12px;
|
|
71
|
+
|
|
72
|
+
/* ---- Superfici senza tratti -------------------------------------------------------------
|
|
73
|
+
La direzione nuova del pannello: a separare sono il colore del fondo e l'ombra, non un
|
|
74
|
+
bordo di un pixel. Un contorno disegna una scatola, e una schermata piena di scatole si
|
|
75
|
+
legge come un modulo da compilare invece che come il contenuto che rappresenta.
|
|
76
|
+
|
|
77
|
+
QUATTRO piani, e non di più — al quinto la gerarchia smette di leggersi:
|
|
78
|
+
|
|
79
|
+
--ak-ground il foglio sotto tutto: PIÙ PROFONDO di `--ak-bg`, ed è questa la leva
|
|
80
|
+
che dà contrasto a una superficie bianca. Con un fondo quasi bianco
|
|
81
|
+
anche lui, una card resta appesa alla sola ombra e sparisce.
|
|
82
|
+
--ak-panel la superficie sollevata (già dichiarata sopra: bianca)
|
|
83
|
+
--ak-inset un blocco incassato DENTRO una superficie
|
|
84
|
+
--ak-inset-deep il pozzetto: vaschette dei segmentati, segnaposto delle immagini
|
|
85
|
+
|
|
86
|
+
Le ombre hanno sempre DUE componenti: una vicina che definisce il bordo e una lontana e
|
|
87
|
+
molto diluita che dà l'altezza. Con la sola vicina una card sembra stampata sul foglio
|
|
88
|
+
invece che appoggiata sopra; con la sola lontana sembra sporca.
|
|
89
|
+
|
|
90
|
+
Stanno qui e non in `admin/src/app.css` perché sono decisioni di aspetto, e questo file è
|
|
91
|
+
l'unica leva di personalizzazione per sito: un cliente con un'identità più fredda cambia
|
|
92
|
+
questi quattro valori e si porta dietro ogni schermata che li usa. Erano dentro `.pw`
|
|
93
|
+
(l'editor dei lavori) finché a usarli era una sola schermata; dalla seconda, una copia
|
|
94
|
+
sarebbe stata la prima occasione per farle divergere.
|
|
95
|
+
|
|
96
|
+
NB: questo file si consuma da `dist/`, non da `src/` — dopo averlo toccato serve
|
|
97
|
+
`npm run build:pkgs`, o l'admin continua a usare gli stili vecchi senza dare errore. */
|
|
98
|
+
--ak-ground: #efeeea;
|
|
99
|
+
--ak-inset: #f4f4f1;
|
|
100
|
+
--ak-inset-deep: #e7e7e2;
|
|
101
|
+
--ak-lift-1: 0 1px 2px rgba(20, 20, 24, .07), 0 5px 12px -8px rgba(20, 20, 24, .28);
|
|
102
|
+
--ak-lift-2: 0 1px 2px rgba(20, 20, 24, .06), 0 10px 24px -14px rgba(20, 20, 24, .35);
|
|
103
|
+
--ak-lift-3: 0 2px 6px rgba(20, 20, 24, .07), 0 28px 56px -28px rgba(20, 20, 24, .45);
|
|
104
|
+
/* L'anello di focus sostituisce il bordo che non c'è: senza, un campo riempito non ha modo
|
|
105
|
+
di dire dove sta il cursore. */
|
|
106
|
+
--ak-ring: 0 0 0 3px color-mix(in srgb, var(--ak-accent) 20%, transparent);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ---- Tema scuro --------------------------------------------------------------------------
|
|
110
|
+
Stessa gerarchia di elevazione del chiaro (ground più profondo di bg, bg più profondo di
|
|
111
|
+
panel), ma invertita in luminanza: in un'interfaccia scura una superficie sale illuminandosi,
|
|
112
|
+
non ombreggiandosi — l'ombra da sola smette di leggersi su un fondo già quasi nero.
|
|
113
|
+
|
|
114
|
+
Non tutto si ridefinisce. Il rail è già scuro anche nel tema chiaro (`--ak-rail-bg`), quindi
|
|
115
|
+
il suo contrasto interno non dipende da questo blocco; le dimensioni (`--ak-radius`,
|
|
116
|
+
`--ak-gap`, le larghezze, `--ak-cell`, i font) non hanno un colore da invertire. `--ak-ring`
|
|
117
|
+
non si ridefinisce nemmeno lui: è già `color-mix(…, var(--ak-accent) …)`, quindi eredita da
|
|
118
|
+
solo il nuovo accento sotto.
|
|
119
|
+
|
|
120
|
+
L'accento non cambia solo tono: `--ak-accent-ink` passa da bianco a un quasi-nero caldo,
|
|
121
|
+
perché serve sia come testo (link, barra di selezione) sia come sfondo pieno di un bottone
|
|
122
|
+
(`.ak-btn-primary`) — un solo hex chiaro non regge bene entrambi i ruoli su un fondo quasi
|
|
123
|
+
nero. Valori verificati per contrasto WCAG (soglia AA 4.5:1 testo, 3:1 componenti UI): ink su
|
|
124
|
+
bg/panel/ground 13-15:1, ink-quiet 6-7:1, ink-faint 4.6-5.3:1, accento come testo 4.7-5.1:1,
|
|
125
|
+
accent-ink su accento pieno 5.5:1.
|
|
126
|
+
|
|
127
|
+
Un sito che in futuro vuole un accento scuro diverso dal default deve scrivere il proprio
|
|
128
|
+
override nello STESSO selettore scoped (`:root[data-theme="dark"]`), non in un `:root`
|
|
129
|
+
semplice: quest'ultimo (specificità 0,1,0) perde sempre contro questo (0,2,0), a prescindere
|
|
130
|
+
dall'ordine di import — un override scritto nel modo sbagliato sparirebbe senza errore non
|
|
131
|
+
appena si passa al tema scuro. */
|
|
132
|
+
:root[data-theme="dark"] {
|
|
133
|
+
color-scheme: dark;
|
|
134
|
+
--ak-ground: #16171a;
|
|
135
|
+
--ak-bg: #1c1d20;
|
|
136
|
+
--ak-col-bg: #1a1b1e;
|
|
137
|
+
--ak-inset: #1a1b1e;
|
|
138
|
+
--ak-inset-deep: #131417;
|
|
139
|
+
--ak-panel: #232428;
|
|
140
|
+
|
|
141
|
+
--ak-line: rgba(255, 255, 255, .12);
|
|
142
|
+
--ak-hover: rgba(255, 255, 255, .06);
|
|
143
|
+
--ak-shadow: 0 1px 2px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255, 255, 255, .05);
|
|
144
|
+
--ak-lift-1: 0 1px 2px rgba(0, 0, 0, .5), 0 6px 16px -8px rgba(0, 0, 0, .6);
|
|
145
|
+
--ak-lift-2: 0 1px 2px rgba(0, 0, 0, .45), 0 12px 28px -14px rgba(0, 0, 0, .65);
|
|
146
|
+
--ak-lift-3: 0 2px 6px rgba(0, 0, 0, .5), 0 30px 60px -28px rgba(0, 0, 0, .7);
|
|
147
|
+
|
|
148
|
+
--ak-ink: #ececea;
|
|
149
|
+
--ak-ink-quiet: #a3a3a0;
|
|
150
|
+
--ak-ink-faint: #8c8c86;
|
|
151
|
+
|
|
152
|
+
--ak-accent: #d9713f;
|
|
153
|
+
--ak-accent-ink: #241209;
|
|
154
|
+
--ak-accent-hover: #c0602f;
|
|
155
|
+
--ak-danger: #ef6a5c;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.ak-form { display: flex; flex-direction: column; gap: calc(var(--ak-gap) * 1.4); }
|
|
159
|
+
|
|
160
|
+
.ak-group {
|
|
161
|
+
border: 1px solid var(--ak-line); border-radius: var(--ak-radius);
|
|
162
|
+
padding: var(--ak-gap); margin: 0;
|
|
163
|
+
display: flex; flex-direction: column; gap: var(--ak-gap);
|
|
164
|
+
background: var(--ak-panel);
|
|
165
|
+
}
|
|
166
|
+
.ak-legend {
|
|
167
|
+
font: 600 var(--ak-fs-small)/1 var(--ak-font);
|
|
168
|
+
text-transform: uppercase; letter-spacing: .08em; color: var(--ak-ink-quiet);
|
|
169
|
+
padding: 0 6px;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.ak-field { display: flex; flex-direction: column; gap: 5px; }
|
|
173
|
+
.ak-field-inline { flex-direction: row; align-items: center; gap: 8px; }
|
|
174
|
+
.ak-label { font: 500 var(--ak-fs)/1.3 var(--ak-font); color: var(--ak-ink); }
|
|
175
|
+
.ak-hint { font: 400 var(--ak-fs-small)/1.4 var(--ak-font); color: var(--ak-ink-quiet); }
|
|
176
|
+
.ak-error { font: 500 var(--ak-fs-small)/1.4 var(--ak-font); color: var(--ak-danger); }
|
|
177
|
+
|
|
178
|
+
.ak-input {
|
|
179
|
+
font: 400 var(--ak-fs)/1.4 var(--ak-font);
|
|
180
|
+
color: var(--ak-ink); background: var(--ak-panel);
|
|
181
|
+
border: 1px solid var(--ak-line); border-radius: var(--ak-radius);
|
|
182
|
+
padding: 8px 10px; width: 100%;
|
|
183
|
+
}
|
|
184
|
+
/* Le caselle e i cursori prendono l'accento del sito invece del blu di sistema. */
|
|
185
|
+
input, select, textarea, button { accent-color: var(--ak-accent); }
|
|
186
|
+
|
|
187
|
+
.ak-input:focus-visible { outline: 2px solid var(--ak-accent); outline-offset: 1px; }
|
|
188
|
+
.ak-textarea { resize: vertical; font-family: var(--ak-font-mono); font-size: var(--ak-fs-small); }
|
|
189
|
+
|
|
190
|
+
.ak-btn {
|
|
191
|
+
font: 500 var(--ak-fs-small)/1 var(--ak-font);
|
|
192
|
+
padding: 7px 12px; border-radius: var(--ak-radius);
|
|
193
|
+
border: 1px solid var(--ak-line); background: var(--ak-panel); color: var(--ak-ink);
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
}
|
|
196
|
+
a.ak-btn { text-decoration: none; display: inline-flex; align-items: center; }
|
|
197
|
+
.ak-btn:hover { border-color: var(--ak-ink-quiet); }
|
|
198
|
+
.ak-btn:disabled { opacity: .5; cursor: default; }
|
|
199
|
+
.ak-btn:disabled:hover { border-color: var(--ak-line); }
|
|
200
|
+
.ak-btn-quiet { color: var(--ak-ink-quiet); }
|
|
201
|
+
/* Il bottone dell'azione principale della schermata — «Salva e pubblica», «Crea». Ce n'è al
|
|
202
|
+
massimo UNO visibile per volta: se due gesti si contendono l'accento, l'accento non indica più
|
|
203
|
+
niente. */
|
|
204
|
+
.ak-btn-primary {
|
|
205
|
+
background: var(--ak-accent); border-color: var(--ak-accent); color: var(--ak-accent-ink);
|
|
206
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
207
|
+
}
|
|
208
|
+
.ak-btn-primary:hover:not(:disabled) { background: var(--ak-accent-hover); border-color: var(--ak-accent-hover); }
|
|
209
|
+
.ak-btn-primary:disabled:hover { border-color: var(--ak-accent); }
|
|
210
|
+
.ak-btn-block { width: 100%; }
|
|
211
|
+
.ak-icon {
|
|
212
|
+
border: 0; background: transparent; cursor: pointer; color: var(--ak-ink-quiet);
|
|
213
|
+
font: 500 var(--ak-fs)/1 var(--ak-font); padding: 2px 6px;
|
|
214
|
+
}
|
|
215
|
+
.ak-icon:hover { color: var(--ak-ink); }
|
|
216
|
+
|
|
217
|
+
.ak-thumb {
|
|
218
|
+
display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
|
|
219
|
+
border-radius: var(--ak-radius); background: var(--ak-line);
|
|
220
|
+
}
|
|
221
|
+
.ak-thumb-empty { opacity: .5; }
|
|
222
|
+
.ak-media-one { display: flex; gap: var(--ak-gap); align-items: flex-start; }
|
|
223
|
+
.ak-media-one .ak-thumb { width: 96px; }
|
|
224
|
+
.ak-media-actions { display: flex; flex-direction: column; gap: 6px; }
|
|
225
|
+
.ak-media-grid {
|
|
226
|
+
display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
|
|
227
|
+
gap: 8px; margin-bottom: 8px;
|
|
228
|
+
}
|
|
229
|
+
.ak-media-item { margin: 0; }
|
|
230
|
+
.ak-media-item-bar { display: flex; justify-content: space-between; align-items: center; }
|
|
231
|
+
/* Voce nascosta (widget r2Curated): resta nell'elenco e al suo posto, ma non va online.
|
|
232
|
+
Si vede spenta, non sparita — è tutta la differenza fra "nascosta" e "tolta". La barra dei
|
|
233
|
+
bottoni resta a piena opacità, altrimenti quello per rimetterla online sarebbe il meno
|
|
234
|
+
leggibile della riga. */
|
|
235
|
+
.ak-media-item.is-hidden .ak-thumb { opacity: .28; filter: grayscale(1); }
|
|
236
|
+
|
|
237
|
+
/* ---- Media: il guscio del modale di scelta ------------------------------------------ */
|
|
238
|
+
.ak-spacer { flex: 1; }
|
|
239
|
+
|
|
240
|
+
.mb-modal {
|
|
241
|
+
position: fixed; inset: 0; z-index: 50; background: rgba(0, 0, 0, .35);
|
|
242
|
+
display: grid; place-items: center; padding: 4vh 4vw;
|
|
243
|
+
}
|
|
244
|
+
.mb-modal-panel {
|
|
245
|
+
background: var(--ak-bg); border-radius: var(--ak-radius);
|
|
246
|
+
width: 100%; max-width: 1100px; max-height: 92vh; overflow: auto; padding: var(--ak-gap);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.mb { display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: var(--ak-gap); align-items: start; }
|
|
250
|
+
.mb-side { position: sticky; top: 0; }
|
|
251
|
+
.mb-main { min-width: 0; }
|
|
252
|
+
|
|
253
|
+
/* ---- Media: le cartelle -------------------------------------------------------------- */
|
|
254
|
+
.mf { display: flex; flex-direction: column; }
|
|
255
|
+
.mf-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }
|
|
256
|
+
.mf-item {
|
|
257
|
+
position: relative; display: flex; align-items: center;
|
|
258
|
+
border: 1px solid transparent; border-radius: 6px; background: transparent;
|
|
259
|
+
}
|
|
260
|
+
.mf-open {
|
|
261
|
+
flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; text-align: left;
|
|
262
|
+
border: 0; background: transparent; cursor: pointer;
|
|
263
|
+
padding: 8px 10px; font: 500 13px/1.3 var(--ak-font); color: var(--ak-ink);
|
|
264
|
+
}
|
|
265
|
+
.mf-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
266
|
+
.mf-count { font: 400 var(--ak-fs-small)/1 var(--ak-font); color: var(--ak-ink-quiet); font-variant-numeric: tabular-nums; }
|
|
267
|
+
.mf-item:hover { background: var(--ak-hover); }
|
|
268
|
+
.mf-item.is-on {
|
|
269
|
+
background: var(--ak-panel); border-color: var(--ak-line);
|
|
270
|
+
box-shadow: var(--ak-shadow), inset 2px 0 0 var(--ak-accent);
|
|
271
|
+
}
|
|
272
|
+
.mf-item.is-on .mf-name { font-weight: 600; }
|
|
273
|
+
/* Bersaglio di uno spostamento. Deve gridare: un drop andato nel posto sbagliato sposta file
|
|
274
|
+
veri dentro il bucket, e la strada indietro è un altro drop. */
|
|
275
|
+
.mf-item.is-over {
|
|
276
|
+
background: var(--ak-panel); border-color: var(--ak-accent); border-style: dashed;
|
|
277
|
+
color: var(--ak-accent);
|
|
278
|
+
}
|
|
279
|
+
.mf-item.is-over .mf-count { color: var(--ak-accent); }
|
|
280
|
+
/* «Senza cartella» è un'altra cosa dalle cartelle: sopra la riga, non nell'elenco. */
|
|
281
|
+
.mf-loose { margin-bottom: 10px; }
|
|
282
|
+
.mf-list + .mf-list { padding-top: 12px; border-top: 1px solid var(--ak-line); }
|
|
283
|
+
.mf-new { margin-top: 10px; align-self: flex-start; }
|
|
284
|
+
/* Compare solo mentre si trascina una cartella: è il bersaglio del primo livello, che prima non
|
|
285
|
+
esisteva — l'unico modo era indovinare che «Tutte» lo fosse. */
|
|
286
|
+
.mf-root-drop {
|
|
287
|
+
margin-top: 10px; padding: 12px 10px; border-radius: var(--ak-radius);
|
|
288
|
+
border: 2px dashed var(--ak-line); text-align: center;
|
|
289
|
+
font: 500 var(--ak-fs-small)/1.3 var(--ak-font); color: var(--ak-ink-quiet);
|
|
290
|
+
}
|
|
291
|
+
.mf-root-drop.is-over { border-color: var(--ak-accent); color: var(--ak-accent); background: var(--ak-panel); }
|
|
292
|
+
/* Il cestino chiude la colonna, staccato: è un posto dove si va, non una cartella fra le altre. */
|
|
293
|
+
.mf-tail { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--ak-line); }
|
|
294
|
+
.mf-ico { flex: none; color: var(--ak-ink-quiet); }
|
|
295
|
+
.mf-item.is-on .mf-ico { color: var(--ak-accent); }
|
|
296
|
+
|
|
297
|
+
.mf-actions { position: relative; flex: none; }
|
|
298
|
+
.mf-more {
|
|
299
|
+
display: flex; border: 0; background: transparent; cursor: pointer; border-radius: 4px;
|
|
300
|
+
color: var(--ak-ink-quiet); padding: 4px 6px; opacity: 0;
|
|
301
|
+
font: 500 var(--ak-fs-small)/1 var(--ak-font);
|
|
302
|
+
}
|
|
303
|
+
.mf-item:hover .mf-more, .mf-item.is-on .mf-more, .mf-more:focus-visible { opacity: 1; }
|
|
304
|
+
.mf-more:hover { background: var(--ak-bg); color: var(--ak-ink); }
|
|
305
|
+
.mf-menu {
|
|
306
|
+
position: absolute; top: calc(100% + 2px); z-index: 30;
|
|
307
|
+
min-width: 200px; padding: 4px; display: flex; flex-direction: column; gap: 1px;
|
|
308
|
+
background: var(--ak-panel); border: 1px solid var(--ak-line); border-radius: 8px;
|
|
309
|
+
box-shadow: 0 12px 30px rgba(0, 0, 0, .16);
|
|
310
|
+
}
|
|
311
|
+
.mf-menu.is-left { right: 0; left: auto; }
|
|
312
|
+
.mf-menu.is-right { left: 0; right: auto; }
|
|
313
|
+
.mf-menu > button {
|
|
314
|
+
border: 0; background: transparent; cursor: pointer; text-align: left; border-radius: 5px;
|
|
315
|
+
padding: 7px 9px; font: 400 13px/1.2 var(--ak-font); color: var(--ak-ink);
|
|
316
|
+
}
|
|
317
|
+
.mf-menu > button:hover { background: var(--ak-bg); }
|
|
318
|
+
.mf-menu > button.mf-danger { color: var(--ak-danger); }
|
|
319
|
+
.mf-menu-form { min-width: 260px; padding: 10px; gap: 8px; }
|
|
320
|
+
.mf-menu-row { display: flex; gap: 6px; }
|
|
321
|
+
|
|
322
|
+
/* ---- Media: la griglia ---------------------------------------------------------------- */
|
|
323
|
+
/* `min-height: 100%`: la zona che riceve i file trascinati è alta quanto il pannello, non
|
|
324
|
+
quanto il suo contenuto. In una cartella vuota — cioè proprio quando si sta caricando — era
|
|
325
|
+
una striscia di quaranta pixel in cima, e tutto il resto dello schermo non riceveva niente. */
|
|
326
|
+
.mg-wrap { display: flex; flex-direction: column; gap: 12px; min-width: 0; min-height: 100%; position: relative; }
|
|
327
|
+
.mg-wrap.is-dropping { outline: 2px dashed var(--ak-accent); outline-offset: -6px; border-radius: var(--ak-radius); }
|
|
328
|
+
.mg-dropzone {
|
|
329
|
+
position: absolute; inset: 0; z-index: 5; pointer-events: none;
|
|
330
|
+
display: grid; place-items: center; border-radius: var(--ak-radius);
|
|
331
|
+
background: rgba(255, 255, 255, .82);
|
|
332
|
+
font: 500 var(--ak-fs)/1.4 var(--ak-font); color: var(--ak-ink);
|
|
333
|
+
}
|
|
334
|
+
.mg-bar { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; min-height: 32px; }
|
|
335
|
+
.mg-all { display: flex; align-items: center; gap: 8px; cursor: pointer; font: 500 13px/1 var(--ak-font); }
|
|
336
|
+
.mg-all input { width: 15px; height: 15px; margin: 0; }
|
|
337
|
+
.mg-act {
|
|
338
|
+
border: 0; background: transparent; cursor: pointer; padding: 4px 0;
|
|
339
|
+
font: 500 13px/1 var(--ak-font); color: var(--ak-accent);
|
|
340
|
+
}
|
|
341
|
+
.mg-act:hover:not(:disabled) { text-decoration: underline; }
|
|
342
|
+
.mg-act:disabled { color: var(--ak-ink-quiet); cursor: default; }
|
|
343
|
+
.mg-act.is-danger { color: var(--ak-danger); }
|
|
344
|
+
.mg-menu-wrap { position: relative; display: inline-flex; }
|
|
345
|
+
.mg-menu {
|
|
346
|
+
position: absolute; top: calc(100% + 4px); left: 0; z-index: 30;
|
|
347
|
+
min-width: 190px; max-height: 320px; overflow: auto; padding: 4px;
|
|
348
|
+
display: flex; flex-direction: column; gap: 1px;
|
|
349
|
+
background: var(--ak-panel); border: 1px solid var(--ak-line); border-radius: 8px;
|
|
350
|
+
box-shadow: 0 12px 30px rgba(0, 0, 0, .16);
|
|
351
|
+
}
|
|
352
|
+
.mg-menu > button {
|
|
353
|
+
display: flex; justify-content: space-between; gap: 12px;
|
|
354
|
+
border: 0; background: transparent; cursor: pointer; text-align: left; border-radius: 5px;
|
|
355
|
+
padding: 7px 9px; font: 400 13px/1.2 var(--ak-font); color: var(--ak-ink);
|
|
356
|
+
}
|
|
357
|
+
.mg-menu > button:hover { background: var(--ak-bg); }
|
|
358
|
+
.mg-sort { font: inherit; border: 1px solid var(--ak-line); border-radius: 4px; padding: 2px 4px; }
|
|
359
|
+
.mg-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
360
|
+
.mg-section { display: flex; flex-direction: column; gap: 10px; }
|
|
361
|
+
.mg-section-head { display: flex; align-items: center; gap: 14px; }
|
|
362
|
+
.mg-section-title {
|
|
363
|
+
margin: 0; font: 600 11px/1 var(--ak-font); text-transform: uppercase; letter-spacing: .09em;
|
|
364
|
+
color: var(--ak-ink-quiet);
|
|
365
|
+
}
|
|
366
|
+
/* L'avanzamento di un'operazione lunga non è una nota a margine: è la risposta alla domanda
|
|
367
|
+
«sta facendo qualcosa?». Se non si vede, chi guarda ricarica la pagina. */
|
|
368
|
+
.mg-progress {
|
|
369
|
+
margin: 0; padding: 8px 12px; border-radius: var(--ak-radius);
|
|
370
|
+
background: var(--ak-panel); border: 1px solid var(--ak-accent);
|
|
371
|
+
font: 500 var(--ak-fs-small)/1.4 var(--ak-font); color: var(--ak-ink);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* Celle di ingombro uguale, immagine INTERA dentro. Prima erano quadrati con `object-fit: cover`:
|
|
375
|
+
un verticale sembrava un quadrato e per riconoscere una foto bisognava aprirla. */
|
|
376
|
+
.mg { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--ak-cell), 1fr)); gap: 18px 14px; }
|
|
377
|
+
.mg-item { margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
|
|
378
|
+
.mg-frame {
|
|
379
|
+
position: relative; height: var(--ak-cell); cursor: pointer;
|
|
380
|
+
display: flex; align-items: center; justify-content: center;
|
|
381
|
+
}
|
|
382
|
+
.mg-img {
|
|
383
|
+
max-width: 100%; max-height: 100%; width: auto; height: auto; display: block;
|
|
384
|
+
background: var(--ak-line); box-shadow: 0 1px 4px rgba(0, 0, 0, .16);
|
|
385
|
+
}
|
|
386
|
+
/* La cornice della selezione è DECORAZIONE: `pointer-events: none` o si prende lei il click.
|
|
387
|
+
Essendo un ::after del frame viene disegnata dopo la casella, quindi le stava sopra: premere
|
|
388
|
+
la spunta di un elemento già selezionato non lo deselezionava, lo apriva. */
|
|
389
|
+
.mg-item.is-on .mg-frame::after {
|
|
390
|
+
content: ""; position: absolute; inset: -6px; pointer-events: none;
|
|
391
|
+
border: 2px solid var(--ak-accent); border-radius: 4px;
|
|
392
|
+
}
|
|
393
|
+
.mg-check {
|
|
394
|
+
position: absolute; left: 4px; bottom: 4px; z-index: 3; width: 20px; height: 20px; border-radius: 4px;
|
|
395
|
+
display: none; align-items: center; justify-content: center; cursor: pointer;
|
|
396
|
+
border: 1px solid var(--ak-line); background: rgba(255, 255, 255, .94);
|
|
397
|
+
font: 700 12px/1 var(--ak-font); color: var(--ak-accent-ink);
|
|
398
|
+
}
|
|
399
|
+
.mg-item:hover .mg-check, .mg-item.is-on .mg-check { display: flex; }
|
|
400
|
+
.mg-item.is-on .mg-check { background: var(--ak-accent); border-color: var(--ak-accent); }
|
|
401
|
+
.mg-cap {
|
|
402
|
+
font: 400 11px/1.3 var(--ak-font); color: var(--ak-ink-quiet); text-align: center;
|
|
403
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/* ---- Media: una cartella dentro la griglia ------------------------------------------- */
|
|
407
|
+
/* Occupa uno slot come una foto: è contenuto anche lei, si seleziona e si trascina — e una cosa
|
|
408
|
+
che si prende e si sposta deve avere la dimensione di un bersaglio, non di un chip. */
|
|
409
|
+
.mg-folder { position: relative; }
|
|
410
|
+
.mg-folder .mg-frame {
|
|
411
|
+
border: 1px solid var(--ak-line); border-radius: var(--ak-radius); background: var(--ak-panel);
|
|
412
|
+
}
|
|
413
|
+
.mg-folder:hover .mg-frame { border-color: var(--ak-ink-quiet); }
|
|
414
|
+
.mg-folder-ico { width: 58%; height: auto; fill: var(--ak-line); stroke: var(--ak-ink-quiet); stroke-width: 1.2; }
|
|
415
|
+
.mg-folder .mg-cap { font-weight: 500; color: var(--ak-ink); }
|
|
416
|
+
/* Bersaglio di un drop: la cartella sta per ricevere qualcosa. */
|
|
417
|
+
.mg-folder.is-over .mg-frame {
|
|
418
|
+
border: 2px dashed var(--ak-accent); background: var(--ak-bg);
|
|
419
|
+
}
|
|
420
|
+
.mg-folder.is-over .mg-folder-ico { fill: var(--ak-panel); stroke: var(--ak-accent); }
|
|
421
|
+
.mg-folder-menu { position: absolute; top: 6px; right: 6px; z-index: 4; }
|
|
422
|
+
.mg-folder-menu .mf-more { background: rgba(255, 255, 255, .92); border: 1px solid var(--ak-line); }
|
|
423
|
+
/* Erano invisibili: `.mf-more` nasce con opacity 0 e la regola che lo accende guarda `.mf-item`,
|
|
424
|
+
cioè la riga della colonna di sinistra. Dentro una cella della griglia non c'è nessun
|
|
425
|
+
`.mf-item`, quindi il menu restava spento anche al passaggio del mouse. */
|
|
426
|
+
.mg-folder:hover .mg-folder-menu .mf-more,
|
|
427
|
+
.mg-folder.is-on .mg-folder-menu .mf-more,
|
|
428
|
+
.mg-folder-menu .mf-more:focus-visible { opacity: 1; }
|
|
429
|
+
.mg-foot {
|
|
430
|
+
position: sticky; bottom: 0; z-index: 2;
|
|
431
|
+
display: flex; align-items: center; gap: 8px; padding: 10px 12px;
|
|
432
|
+
background: var(--ak-panel); border: 1px solid var(--ak-line); border-radius: var(--ak-radius);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/* ---- Media: la foto a schermo intero -------------------------------------------------- */
|
|
436
|
+
.lb { position: fixed; inset: 0; z-index: 60; background: #000; display: flex; flex-direction: column; }
|
|
437
|
+
.lb-top {
|
|
438
|
+
flex: none; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px;
|
|
439
|
+
padding: 10px 14px; color: #fff;
|
|
440
|
+
}
|
|
441
|
+
.lb-id { display: flex; flex-direction: column; align-items: center; gap: 2px; }
|
|
442
|
+
.lb-name { font: 500 13px/1.2 var(--ak-font); }
|
|
443
|
+
.lb-count { font: 400 12px/1 var(--ak-font); opacity: .6; }
|
|
444
|
+
.lb-tools { display: flex; justify-content: flex-end; gap: 2px; }
|
|
445
|
+
.lb-btn {
|
|
446
|
+
display: inline-flex; align-items: center; gap: 6px; text-decoration: none;
|
|
447
|
+
border: 0; background: transparent; color: #fff; cursor: pointer; border-radius: 6px;
|
|
448
|
+
padding: 8px 10px; font: 500 13px/1 var(--ak-font);
|
|
449
|
+
}
|
|
450
|
+
.lb-btn:hover { background: rgba(255, 255, 255, .13); }
|
|
451
|
+
.lb-btn.is-on { background: rgba(255, 255, 255, .2); }
|
|
452
|
+
.lb-tools .lb-btn { min-width: 34px; justify-content: center; }
|
|
453
|
+
.lb-stage {
|
|
454
|
+
flex: 1; min-height: 0; position: relative;
|
|
455
|
+
display: flex; align-items: center; justify-content: center; padding: 0 66px 22px;
|
|
456
|
+
}
|
|
457
|
+
.lb-img { max-width: 100%; max-height: 100%; object-fit: contain; }
|
|
458
|
+
.lb-nav {
|
|
459
|
+
position: absolute; top: 50%; transform: translateY(-50%);
|
|
460
|
+
width: 44px; height: 44px; border-radius: 50%; border: 0; cursor: pointer;
|
|
461
|
+
background: rgba(255, 255, 255, .14); color: #fff; font: 400 24px/1 var(--ak-font);
|
|
462
|
+
}
|
|
463
|
+
.lb-nav:hover:not(:disabled) { background: rgba(255, 255, 255, .26); }
|
|
464
|
+
.lb-nav:disabled { opacity: .2; cursor: default; }
|
|
465
|
+
.lb-prev { left: 12px; }
|
|
466
|
+
.lb-next { right: 12px; }
|
|
467
|
+
.lb-info {
|
|
468
|
+
position: absolute; right: 14px; top: 58px; width: 290px; z-index: 2;
|
|
469
|
+
background: rgba(22, 22, 22, .94); border: 1px solid rgba(255, 255, 255, .16);
|
|
470
|
+
border-radius: 8px; padding: 12px 14px; color: #eaeaea;
|
|
471
|
+
}
|
|
472
|
+
.lb-info dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 5px 14px; font: 400 12px/1.4 var(--ak-font); }
|
|
473
|
+
.lb-info dt { color: #9b9b98; }
|
|
474
|
+
.lb-info dd { margin: 0; word-break: break-word; }
|
|
475
|
+
|
|
476
|
+
/* ---- Media: il dialogo di caricamento ------------------------------------------------- */
|
|
477
|
+
.up { position: fixed; inset: 0; z-index: 70; background: rgba(0, 0, 0, .42); display: grid; place-items: center; padding: 5vh 5vw; }
|
|
478
|
+
.up-panel {
|
|
479
|
+
position: relative; width: 100%; max-width: 620px; padding: 30px 28px 24px;
|
|
480
|
+
display: flex; flex-direction: column; gap: 12px;
|
|
481
|
+
background: var(--ak-panel); border-radius: 10px; box-shadow: 0 24px 60px rgba(0, 0, 0, .3);
|
|
482
|
+
}
|
|
483
|
+
.up-close {
|
|
484
|
+
position: absolute; top: 8px; right: 12px; border: 0; background: transparent; cursor: pointer;
|
|
485
|
+
color: var(--ak-ink-quiet); font: 400 22px/1 var(--ak-font);
|
|
486
|
+
}
|
|
487
|
+
.up-drop {
|
|
488
|
+
display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 40px 20px;
|
|
489
|
+
border: 2px dashed var(--ak-line); border-radius: 8px; background: var(--ak-bg);
|
|
490
|
+
}
|
|
491
|
+
.up-drop.is-over { border-color: var(--ak-accent); background: #fdf4f2; }
|
|
492
|
+
.up-cloud { color: var(--ak-ink-quiet); }
|
|
493
|
+
.up-hint { margin: 0; font: 400 13px/1.4 var(--ak-font); color: var(--ak-ink-quiet); }
|
|
494
|
+
.up-dest { margin: 0; font: 400 var(--ak-fs-small)/1.4 var(--ak-font); color: var(--ak-ink-quiet); }
|
|
495
|
+
|
|
496
|
+
/* ---- Cestino ------------------------------------------------------------------------ */
|
|
497
|
+
.tr { display: flex; flex-direction: column; gap: 10px; }
|
|
498
|
+
.tr-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
499
|
+
.tr-row {
|
|
500
|
+
display: flex; align-items: center; gap: 10px; padding: 8px 10px;
|
|
501
|
+
background: var(--ak-panel); border: 1px solid var(--ak-line); border-radius: var(--ak-radius);
|
|
502
|
+
}
|
|
503
|
+
.tr-thumb { width: 44px; height: 44px; object-fit: cover; border-radius: 4px; background: var(--ak-line); }
|
|
504
|
+
.tr-name { font: 500 var(--ak-fs-small)/1.3 var(--ak-font); }
|
|
505
|
+
.tr-orig { flex: 1; font: 400 11px/1.3 var(--ak-font-mono); color: var(--ak-ink-quiet);
|
|
506
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
507
|
+
|
|
508
|
+
/* ---- objectList (l'unico widget ricorsivo) ------------------------------------------- */
|
|
509
|
+
.ol-obj { display: flex; flex-direction: column; gap: var(--ak-gap); }
|
|
510
|
+
.ol-list {
|
|
511
|
+
border: 1px dashed var(--ak-line); border-radius: var(--ak-radius);
|
|
512
|
+
padding: 10px; margin: 0; display: flex; flex-direction: column; gap: 10px;
|
|
513
|
+
}
|
|
514
|
+
.ol-item {
|
|
515
|
+
border: 1px solid var(--ak-line); border-radius: var(--ak-radius);
|
|
516
|
+
padding: 10px; display: flex; flex-direction: column; gap: 10px; background: var(--ak-bg);
|
|
517
|
+
}
|
|
518
|
+
.ol-item-bar { display: flex; align-items: center; gap: 4px; }
|
|
519
|
+
|
|
520
|
+
/* ---- Anteprima locale (pannello di Regia) ------------------------------------------- */
|
|
521
|
+
.rg { display: flex; flex-direction: column; gap: 10px; max-width: 720px; }
|
|
522
|
+
.rg-top {
|
|
523
|
+
display: flex; align-items: center; gap: 10px; padding: 10px 12px;
|
|
524
|
+
background: var(--ak-panel); border: 1px solid var(--ak-line); border-radius: var(--ak-radius);
|
|
525
|
+
}
|
|
526
|
+
.rg-name { font: 600 var(--ak-fs-small)/1.3 var(--ak-font); }
|
|
527
|
+
.rg-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--ak-ink-quiet); flex: none; }
|
|
528
|
+
.rg-dot-running { background: #3faa72; }
|
|
529
|
+
.rg-dot-starting { background: #c08a2a; }
|
|
530
|
+
.rg-dot-crashed, .rg-dot-failed { background: #b34a3f; }
|
|
531
|
+
.rg-lan {
|
|
532
|
+
display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap;
|
|
533
|
+
padding: 10px 12px; border: 1px solid var(--ak-line); border-radius: var(--ak-radius);
|
|
534
|
+
}
|
|
535
|
+
.rg-lan-urls { flex: 1 1 16rem; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
536
|
+
.rg-qr { flex: none; width: 128px; height: 128px; border-radius: 4px; }
|
|
537
|
+
|
|
538
|
+
/* ---- Il campo di prosa (testo formattato) ----------------------------------------------
|
|
539
|
+
Un `contenteditable`, non una textarea: chi usa il pannello vede il grassetto in grassetto e
|
|
540
|
+
i link come link, mai gli asterischi. Vedi form/prose/ProseField.tsx.
|
|
541
|
+
|
|
542
|
+
Il carattere è quello del testo, NON `--ak-font-mono`: `.ak-textarea` lo imposta a spaziatura
|
|
543
|
+
fissa perché lì dentro c'era markdown da leggere carattere per carattere, e qui invece si
|
|
544
|
+
guarda un testo. Va sovrascritto, altrimenti una biografia sembra un file di configurazione.
|
|
545
|
+
---------------------------------------------------------------------------------------- */
|
|
546
|
+
.ak-prose-field {
|
|
547
|
+
font-family: var(--ak-font); white-space: pre-wrap; overflow-wrap: break-word;
|
|
548
|
+
cursor: text; resize: none; height: auto;
|
|
549
|
+
}
|
|
550
|
+
.ak-prose-field:focus { outline: 0; box-shadow: var(--ak-ring); }
|
|
551
|
+
.ak-prose-field p { margin: 0; }
|
|
552
|
+
.ak-prose-field p + p { margin-top: .85em; }
|
|
553
|
+
.ak-prose-field strong { font-weight: 650; }
|
|
554
|
+
/* I collegamenti si vedono che lo sono: è metà del senso di mostrare il testo formattato. */
|
|
555
|
+
.ak-prose-field a { color: var(--ak-accent); text-decoration: underline; text-underline-offset: 2px; }
|
|
556
|
+
/* Il segnaposto: un campo vuoto contiene comunque un `<p><br></p>`, quindi `:empty` non
|
|
557
|
+
scatterebbe mai — lo stato «vuoto» lo dichiara il componente, che conosce il valore. */
|
|
558
|
+
.ak-prose-field.is-empty::before {
|
|
559
|
+
content: attr(data-placeholder); display: block; white-space: pre-wrap;
|
|
560
|
+
color: color-mix(in srgb, var(--ak-ink-quiet) 75%, transparent); pointer-events: none;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/* ---- La barra di formattazione sopra la selezione -------------------------------------
|
|
564
|
+
Appartiene alla PAGINA e non al campo: è disegnata in un portal su `document.body` e
|
|
565
|
+
posizionata con `position: fixed` da `ProseArea`, che sa dov'è la selezione. Dentro il campo
|
|
566
|
+
sarebbe prigioniera del suo `overflow`. Vedi form/prose/ProseBar.tsx.
|
|
567
|
+
|
|
568
|
+
`--ak-prose-bar-h` è dichiarata qui e LETTA DAL CODICE (la costante `BAR_H`): serve a
|
|
569
|
+
decidere se la barra ci sta sopra la selezione prima di disegnarla, e misurarla davvero
|
|
570
|
+
vorrebbe dire un salto visibile a ogni selezione. Se cambia l'altezza, cambia là. --------- */
|
|
571
|
+
.ak-prose-bar {
|
|
572
|
+
--ak-prose-bar-h: 40px;
|
|
573
|
+
position: fixed; z-index: 60; height: var(--ak-prose-bar-h);
|
|
574
|
+
display: flex; align-items: center; gap: 2px; padding: 0 6px;
|
|
575
|
+
border-radius: 10px; background: var(--ak-panel); box-shadow: var(--ak-lift-3);
|
|
576
|
+
/* Il testo sotto si continua a selezionare col mouse: la barra non intercetta i movimenti
|
|
577
|
+
del puntatore fuori dai suoi bottoni. */
|
|
578
|
+
pointer-events: auto;
|
|
579
|
+
}
|
|
580
|
+
.ak-prose-btn {
|
|
581
|
+
display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
|
|
582
|
+
border: 0; border-radius: 7px; background: transparent; color: var(--ak-ink);
|
|
583
|
+
cursor: pointer; font: 500 13px/1 var(--ak-font);
|
|
584
|
+
}
|
|
585
|
+
.ak-prose-btn:hover { background: var(--ak-inset); }
|
|
586
|
+
.ak-prose-btn:focus-visible { outline: 0; box-shadow: var(--ak-ring); }
|
|
587
|
+
.ak-prose-btn.is-bold { font-weight: 700; }
|
|
588
|
+
.ak-prose-btn.is-italic { font-style: italic; font-family: Georgia, serif; }
|
|
589
|
+
/* Il link acceso quando la selezione è già dentro un collegamento: è la sola cosa che
|
|
590
|
+
distingue «aggiungi» da «modifica» prima di aprire il dialogo. */
|
|
591
|
+
.ak-prose-btn.is-on { color: var(--ak-accent); }
|
|
592
|
+
.ak-prose-sep { width: 1px; height: 18px; margin: 0 4px; background: var(--ak-line); }
|
|
593
|
+
|
|
594
|
+
/* Il dialogo del collegamento. Non riusa `.pe-modal` del pannello: quello vive in app.css, che
|
|
595
|
+
adminkit non conosce — il motore non può dipendere dal foglio di chi lo monta. */
|
|
596
|
+
.ak-prose-modal {
|
|
597
|
+
position: fixed; inset: 0; z-index: 70; display: grid; place-items: center;
|
|
598
|
+
background: rgba(0, 0, 0, .35); padding: 20px;
|
|
599
|
+
}
|
|
600
|
+
.ak-prose-card {
|
|
601
|
+
width: min(460px, 100%); border-radius: 14px; background: var(--ak-panel);
|
|
602
|
+
box-shadow: var(--ak-lift-3); overflow: hidden;
|
|
603
|
+
}
|
|
604
|
+
.ak-prose-card header {
|
|
605
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
606
|
+
padding: 16px 18px 12px;
|
|
607
|
+
}
|
|
608
|
+
.ak-prose-card h2 { margin: 0; font: 600 15px/1.2 var(--ak-font); }
|
|
609
|
+
.ak-prose-card header button {
|
|
610
|
+
border: 0; background: transparent; color: var(--ak-ink-quiet); cursor: pointer;
|
|
611
|
+
font-size: 20px; line-height: 1; padding: 0 4px;
|
|
612
|
+
}
|
|
613
|
+
/* Le tre schede in una vaschetta incassata: è una scelta fra tre, non tre bottoni. Stessa
|
|
614
|
+
grammatica di `.seg` nel pannello. */
|
|
615
|
+
.ak-prose-tabs {
|
|
616
|
+
display: flex; gap: 2px; margin: 0 18px; padding: 2px;
|
|
617
|
+
border-radius: 9px; background: var(--ak-inset-deep, var(--ak-inset));
|
|
618
|
+
}
|
|
619
|
+
.ak-prose-tab {
|
|
620
|
+
flex: 1; height: 30px; border: 0; border-radius: 7px; background: transparent;
|
|
621
|
+
color: var(--ak-ink-quiet); cursor: pointer; font: 500 12px/1 var(--ak-font);
|
|
622
|
+
}
|
|
623
|
+
.ak-prose-tab:hover { color: var(--ak-ink); }
|
|
624
|
+
.ak-prose-tab.is-on { background: var(--ak-panel); color: var(--ak-ink); box-shadow: var(--ak-lift-1); }
|
|
625
|
+
.ak-prose-body { padding: 16px 18px 4px; }
|
|
626
|
+
.ak-prose-body .ak-input { width: 100%; }
|
|
627
|
+
.ak-prose-card footer {
|
|
628
|
+
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
629
|
+
padding: 16px 18px 18px;
|
|
630
|
+
}
|
|
631
|
+
.ak-prose-card footer > div { display: flex; gap: 8px; margin-left: auto; }
|
|
632
|
+
.ak-prose-unlink {
|
|
633
|
+
border: 0; background: transparent; color: var(--ak-danger); cursor: pointer;
|
|
634
|
+
font: 500 12px/1 var(--ak-font); padding: 6px 2px;
|
|
635
|
+
}
|
|
636
|
+
.ak-prose-unlink:hover { text-decoration: underline; }
|
package/dist/yaml.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class YamlEmitError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
/** Stringa YAML fra doppi apici, sicura su una riga sola. */
|
|
5
|
+
export declare function yamlStr(value: unknown): string;
|
|
6
|
+
/** Scalare non quotato dove è sicuro (numeri, booleani), quotato altrimenti. */
|
|
7
|
+
export declare function yamlScalar(value: unknown): string;
|
|
8
|
+
export declare function toYamlLines(value: unknown, indent?: number, maxDepth?: number): string[];
|