@klodd/ds 1.1.0 → 3.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/css/00-primitives.css +62 -0
- package/css/10-semantic.css +81 -20
- package/css/apps/ekonom.css +9 -0
- package/css/base/layout.css +45 -0
- package/css/components/auth.css +28 -0
- package/css/components/avatar.css +31 -0
- package/css/components/badge.css +2 -2
- package/css/components/banner.css +63 -0
- package/css/components/chip.css +257 -0
- package/css/components/collapsible.css +64 -0
- package/css/components/divider.css +25 -0
- package/css/components/dropdown.css +88 -0
- package/css/components/feedback.css +6 -0
- package/css/components/form.css +67 -0
- package/css/components/hbar.css +64 -0
- package/css/components/hero.css +85 -0
- package/css/components/hub-card.css +100 -0
- package/css/components/inline-edit.css +67 -0
- package/css/components/input.css +1 -1
- package/css/components/list-row.css +115 -0
- package/css/components/overlay.css +3 -0
- package/css/components/panel.css +95 -0
- package/css/components/progress.css +39 -0
- package/css/components/setting-row.css +186 -0
- package/css/components/split-bar.css +53 -0
- package/css/components/stat.css +55 -0
- package/css/components/swipe-stack.css +200 -0
- package/css/components/tab-bar.css +58 -0
- package/css/components/table.css +39 -0
- package/css/components/tooltip.css +50 -0
- package/css/components/upload-spinner.css +55 -0
- package/css/index.css +32 -0
- package/css/utilities.css +81 -0
- package/js/bar-styles.js +37 -0
- package/js/hero-roll.js +287 -0
- package/js/index.js +95 -0
- package/js/lucide-init.js +27 -0
- package/js/nav-optimistic.js +74 -0
- package/js/pull-to-refresh.js +162 -0
- package/js/pwa-register.js +132 -0
- package/js/sheet-drag.js +163 -0
- package/js/turbo-nav.js +353 -0
- package/package.json +4 -3
package/js/turbo-nav.js
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/*--------------------------------------------------------------
|
|
2
|
+
Sprint I + I.1: Turbo Drive-monstret for Ekonom.
|
|
3
|
+
|
|
4
|
+
Bakgrund (CE 2026-04-27):
|
|
5
|
+
Cross-document View Transitions glitchar pa iOS Safari + PWA-
|
|
6
|
+
standalone (snapshot-bug pa fixed-position-element + dvh-
|
|
7
|
+
instabilitet pa korta sidor utan scroll). Sprint G3+G4 patchade
|
|
8
|
+
symptom utan att losa rotorsaken. Industri-konsensus: skip cross-
|
|
9
|
+
document VT, ga till same-document via fetch + DOM-swap.
|
|
10
|
+
|
|
11
|
+
Detta ar Hotwire/Turbo-monstret applicerat pa Ekonom. Vi behaller
|
|
12
|
+
hela MPA-arkitekturen (Jinja-render, server-routes, Alembic, auth,
|
|
13
|
+
forms via 303-redirect) men intercepterar `<a>`-klick pa interna
|
|
14
|
+
lankar och swappar `<main>` + `<title>` + body-data-attribut
|
|
15
|
+
istallet for full document-navigation. document.startViewTransition
|
|
16
|
+
ger same-document VT som inte triggar iOS-snapshot-bugen.
|
|
17
|
+
|
|
18
|
+
Sprint I.1 (post-Chat-ADR-review): polish + risk-mitigation:
|
|
19
|
+
- history.state merge (inte radera) sa browser-internals (scroll-
|
|
20
|
+
position-cache, etc.) bevaras
|
|
21
|
+
- scrollY save/restore via history.state for korrekt back/forward-
|
|
22
|
+
beteende (browser cachar inte scrollY pa same-document swap)
|
|
23
|
+
- inFlight-guard mot overlappande VT (race condition vid snabba
|
|
24
|
+
dubbel-tap)
|
|
25
|
+
- Focus flyttas till <main> efter swap for screen reader-support
|
|
26
|
+
- Toast vid fetch-fel innan fallback till full document-load
|
|
27
|
+
- Title-safety vid saknat <title>-element
|
|
28
|
+
|
|
29
|
+
Vad vi swappar:
|
|
30
|
+
- <main id="main"> (per-template content inkl. topbar)
|
|
31
|
+
- <title>
|
|
32
|
+
- body data-ptr-enabled (Sprint E1)
|
|
33
|
+
- active-class pa bottom-nav (server-render ar sanning)
|
|
34
|
+
|
|
35
|
+
Vad vi INTE rorr:
|
|
36
|
+
- Bottom-nav-element (sitter utanfor main, oforandrad mellan sidor)
|
|
37
|
+
- <dialog class="sheet"> (inkluderas via base.html, oforandrad)
|
|
38
|
+
- data-first-load (sätts bara forsta besoket, inte vid swap)
|
|
39
|
+
- Form-submits (full document-load via 303-redirect, oforandrat)
|
|
40
|
+
|
|
41
|
+
Fallback:
|
|
42
|
+
- Modifier-klick (cmd/ctrl/shift/alt) eller middle-click: browser
|
|
43
|
+
default (oppna i ny flik)
|
|
44
|
+
- target="_blank" eller download: browser default
|
|
45
|
+
- data-turbo="false" pa <a>: full navigation
|
|
46
|
+
- External origin: full navigation
|
|
47
|
+
- Hash-only links (#anchor): browser default
|
|
48
|
+
- Fetch-fel: toast + fallback till window.location.href
|
|
49
|
+
- Browser utan startViewTransition: instant swap utan animation
|
|
50
|
+
|
|
51
|
+
JS-state-leaks-vigilance (Sprint I.1):
|
|
52
|
+
Eftersom vi inte langre gor full document-reload kan module-level
|
|
53
|
+
state lacka over nav-byten. Konventioner:
|
|
54
|
+
- All event-handling SKA vara delegerad pa document/window-niva
|
|
55
|
+
eller pa element som inte swappas (body, <dialog>-elements i
|
|
56
|
+
base.html). INGA listeners attached till elements i <main>.
|
|
57
|
+
- Inga setInterval utan motsvarande clearInterval-cleanup-trigger
|
|
58
|
+
- Inga module-level array/object-collections utan cleanup-mekanism
|
|
59
|
+
- MutationObserver-pattern: observer maste targeta element utanfor
|
|
60
|
+
<main>, eller disconnect:as via turbo:navigated-event
|
|
61
|
+
--------------------------------------------------------------*/
|
|
62
|
+
( function () {
|
|
63
|
+
'use strict';
|
|
64
|
+
|
|
65
|
+
const ORIGIN = window.location.origin;
|
|
66
|
+
let currentController = null;
|
|
67
|
+
let inFlightSwap = null; // Promise som resolvar nar pagaende VT/swap ar klar.
|
|
68
|
+
|
|
69
|
+
/*--------------------------------------------------------------
|
|
70
|
+
Lank-eligibility: ska denna <a> hanteras av Turbo eller browsern?
|
|
71
|
+
--------------------------------------------------------------*/
|
|
72
|
+
function isInternalLink ( a ) {
|
|
73
|
+
if ( ! a || ! a.href ) return false;
|
|
74
|
+
if ( a.dataset.turbo === 'false' ) return false;
|
|
75
|
+
if ( a.target && a.target !== '' && a.target !== '_self' ) return false;
|
|
76
|
+
if ( a.hasAttribute( 'download' ) ) return false;
|
|
77
|
+
const rawHref = a.getAttribute( 'href' ) || '';
|
|
78
|
+
if ( rawHref.startsWith( '#' ) ) return false;
|
|
79
|
+
if ( rawHref.startsWith( 'mailto:' ) ) return false;
|
|
80
|
+
if ( rawHref.startsWith( 'tel:' ) ) return false;
|
|
81
|
+
try {
|
|
82
|
+
const url = new URL( a.href );
|
|
83
|
+
if ( url.origin !== ORIGIN ) return false;
|
|
84
|
+
} catch ( _ ) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isModifierClick ( e ) {
|
|
91
|
+
if ( e.metaKey || e.ctrlKey || e.shiftKey || e.altKey ) return true;
|
|
92
|
+
if ( e.button !== undefined && e.button !== 0 ) return true;
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/*--------------------------------------------------------------
|
|
97
|
+
Sprint J.4: detektera month-change-nav for att skip:a VT.
|
|
98
|
+
Skalet: VT-snapshot doljer original DOM under fade-tid (~160ms).
|
|
99
|
+
Hero-roll-animation kan inte synkroniseras med VT-fade eftersom
|
|
100
|
+
snapshot blockerar live-DOM. Skip VT vid month-change ger
|
|
101
|
+
anvandaren omedelbar feedback (rollers borjar rulla direkt).
|
|
102
|
+
VT behalls for andra nav-byten (Hem -> Kategorier etc) dar
|
|
103
|
+
cross-fade ar fortsatt vardefull.
|
|
104
|
+
--------------------------------------------------------------*/
|
|
105
|
+
function isMonthChangeNav ( fromUrl, toUrl ) {
|
|
106
|
+
try {
|
|
107
|
+
const f = new URL( fromUrl );
|
|
108
|
+
const t = new URL( toUrl );
|
|
109
|
+
if ( f.origin !== t.origin ) return false;
|
|
110
|
+
if ( f.pathname !== t.pathname ) return false;
|
|
111
|
+
const fromMonth = f.searchParams.get( 'month' );
|
|
112
|
+
const toMonth = t.searchParams.get( 'month' );
|
|
113
|
+
return fromMonth !== toMonth;
|
|
114
|
+
} catch ( _ ) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/*--------------------------------------------------------------
|
|
120
|
+
history.state-helpers. Sprint I.1: merge-pattern istallet for
|
|
121
|
+
radera, sa eventuella browser-cachade state-falt (scroll, etc.)
|
|
122
|
+
bevaras nar vi adderar var turbo-flagga.
|
|
123
|
+
--------------------------------------------------------------*/
|
|
124
|
+
function mergeState ( extra ) {
|
|
125
|
+
return Object.assign( {}, history.state || {}, extra, { turbo: true } );
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function saveScrollOnCurrentEntry () {
|
|
129
|
+
const merged = mergeState( { scrollY: window.scrollY } );
|
|
130
|
+
history.replaceState( merged, '', window.location.href );
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/*--------------------------------------------------------------
|
|
134
|
+
Hamta + parse HTML-respons fran Turbo-fetch.
|
|
135
|
+
--------------------------------------------------------------*/
|
|
136
|
+
async function turboFetch ( url, signal ) {
|
|
137
|
+
const resp = await fetch( url, {
|
|
138
|
+
headers: { 'X-Turbo': 'true', 'Accept': 'text/html' },
|
|
139
|
+
credentials: 'same-origin',
|
|
140
|
+
signal: signal,
|
|
141
|
+
} );
|
|
142
|
+
if ( ! resp.ok ) {
|
|
143
|
+
throw new Error( 'HTTP ' + resp.status );
|
|
144
|
+
}
|
|
145
|
+
const text = await resp.text();
|
|
146
|
+
const doc = new DOMParser().parseFromString( text, 'text/html' );
|
|
147
|
+
return { doc: doc, finalUrl: resp.url };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/*--------------------------------------------------------------
|
|
151
|
+
Utfor sjalva DOM-bytet. Kor inom document.startViewTransition-
|
|
152
|
+
callback for same-document VT.
|
|
153
|
+
--------------------------------------------------------------*/
|
|
154
|
+
function performSwap ( newDoc ) {
|
|
155
|
+
// Title - safety mot saknat title-element (osannolikt men ratt-pa-papper).
|
|
156
|
+
const newTitle = newDoc.querySelector( 'title' );
|
|
157
|
+
if ( newTitle && newTitle.textContent ) {
|
|
158
|
+
document.title = newTitle.textContent;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Body data-attribut. Synka data-ptr-enabled (Sprint E1) sa pull-to-
|
|
162
|
+
// refresh aktiveras/inaktiveras per route. Lat data-first-load styras
|
|
163
|
+
// av initial-render bara - om server skickade ny first-load-true (t.ex.
|
|
164
|
+
// inkognito-besok via turbo) ignorerar vi det for att inte trigga
|
|
165
|
+
// splash-animation per turbo-byte.
|
|
166
|
+
const newBody = newDoc.body;
|
|
167
|
+
if ( newBody.hasAttribute( 'data-ptr-enabled' ) ) {
|
|
168
|
+
document.body.setAttribute( 'data-ptr-enabled', newBody.getAttribute( 'data-ptr-enabled' ) );
|
|
169
|
+
} else {
|
|
170
|
+
document.body.removeAttribute( 'data-ptr-enabled' );
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Main content (inkl. per-template topbar). Replace bevarar element-
|
|
174
|
+
// referenser for VT-name-mapping i same-document VT.
|
|
175
|
+
const oldMain = document.getElementById( 'main' );
|
|
176
|
+
const newMain = newDoc.getElementById( 'main' );
|
|
177
|
+
if ( oldMain && newMain ) {
|
|
178
|
+
oldMain.replaceWith( newMain );
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Bottom-nav active-class. Server-render ar sanning - om optimistic
|
|
182
|
+
// active-flytt pa F1 hamnade fel (t.ex. server-redirect till annan
|
|
183
|
+
// route) sa korrigerar vi den har.
|
|
184
|
+
const newNav = newDoc.querySelector( '.bottom-nav' );
|
|
185
|
+
const liveNav = document.querySelector( '.bottom-nav' );
|
|
186
|
+
if ( newNav && liveNav ) {
|
|
187
|
+
const newActiveHref = newNav.querySelector( '.nav-pod.active' );
|
|
188
|
+
const liveActive = liveNav.querySelector( '.nav-pod.active' );
|
|
189
|
+
if ( liveActive ) liveActive.classList.remove( 'active' );
|
|
190
|
+
if ( newActiveHref ) {
|
|
191
|
+
const target = liveNav.querySelector(
|
|
192
|
+
'a[href="' + newActiveHref.getAttribute( 'href' ) + '"]'
|
|
193
|
+
);
|
|
194
|
+
if ( target ) target.classList.add( 'active' );
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/*--------------------------------------------------------------
|
|
200
|
+
Focus-management efter swap. Sprint I.1: flytta focus till
|
|
201
|
+
<main>-elementet sa screen readers far en logisk forflyttnings-
|
|
202
|
+
punkt. Native MPA-nav rensar focus implicit; same-document swap
|
|
203
|
+
maste vi gora explicit.
|
|
204
|
+
--------------------------------------------------------------*/
|
|
205
|
+
function moveFocusToMain () {
|
|
206
|
+
const main = document.getElementById( 'main' );
|
|
207
|
+
if ( ! main ) return;
|
|
208
|
+
// tabindex=-1 om saknat sa programmatic focus funkar utan att
|
|
209
|
+
// adda main till tab-ordningen.
|
|
210
|
+
if ( ! main.hasAttribute( 'tabindex' ) ) {
|
|
211
|
+
main.setAttribute( 'tabindex', '-1' );
|
|
212
|
+
}
|
|
213
|
+
try { main.focus( { preventScroll: true } ); } catch ( _ ) { /* ignore */ }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/*--------------------------------------------------------------
|
|
217
|
+
Kornplats: hamta + swappa + uppdatera history. Anropas vid
|
|
218
|
+
nav-klick OCH popstate (back/forward).
|
|
219
|
+
|
|
220
|
+
Sprint I.1: vantar pa pagaende inFlightSwap innan ny startas
|
|
221
|
+
sa overlappande VT inte ger artifakter vid snabba dubbel-tap.
|
|
222
|
+
--------------------------------------------------------------*/
|
|
223
|
+
async function navigateTo ( url, options ) {
|
|
224
|
+
options = options || {};
|
|
225
|
+
|
|
226
|
+
// Sprint J: spara fromUrl FORE history.pushState eller swap sa
|
|
227
|
+
// turbo:navigated-subscribers (t.ex. hero-roll.js) kan jamfora
|
|
228
|
+
// gammal vs ny route for trigger-detektering (manadsbyte etc.).
|
|
229
|
+
const fromUrl = window.location.href;
|
|
230
|
+
|
|
231
|
+
// Avbryt pagaende fetch om en ny startar (snabba klick).
|
|
232
|
+
if ( currentController ) currentController.abort();
|
|
233
|
+
currentController = new AbortController();
|
|
234
|
+
const myController = currentController;
|
|
235
|
+
|
|
236
|
+
// Vanta pa eventuell pagaende swap (VT) sa vi inte staplar dem.
|
|
237
|
+
if ( inFlightSwap ) {
|
|
238
|
+
try { await inFlightSwap; } catch ( _ ) { /* ignore */ }
|
|
239
|
+
if ( myController.signal.aborted ) return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Sprint I.1: spara nuvarande scrollY i history.state SA fort en
|
|
243
|
+
// nav startar - sa popstate-handlern kan restore:a scrollY nar
|
|
244
|
+
// anvandaren back:ar tillbaka till denna sida.
|
|
245
|
+
if ( ! options.popstate ) {
|
|
246
|
+
saveScrollOnCurrentEntry();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
const { doc, finalUrl } = await turboFetch( url, myController.signal );
|
|
251
|
+
if ( myController.signal.aborted ) return;
|
|
252
|
+
|
|
253
|
+
// Server kan ha redirected (t.ex. /bolanet -> /bolanet?month=2026-04).
|
|
254
|
+
// Anvand finalUrl for history-state sa back/forward funkar korrekt.
|
|
255
|
+
const swap = function () {
|
|
256
|
+
performSwap( doc );
|
|
257
|
+
// Sprint J.3: dispatcha SYNKRON 'turbo:swap'-event INOM
|
|
258
|
+
// swap-callback fore VT slut-snapshot tas. Subscribers (hero-
|
|
259
|
+
// roll.js) kan modifiera nya DOM (t.ex. byta ut hero-amount
|
|
260
|
+
// till digit-rollers) sa VT slut-state inkluderar deras
|
|
261
|
+
// modifikationer. Forhindrar 0.2s-flash av server-text
|
|
262
|
+
// under VT-fade vid month-change.
|
|
263
|
+
document.dispatchEvent( new CustomEvent( 'turbo:swap', {
|
|
264
|
+
detail: { url: finalUrl, fromUrl: fromUrl, popstate: !! options.popstate },
|
|
265
|
+
} ) );
|
|
266
|
+
if ( options.popstate ) {
|
|
267
|
+
// Restore scrollY fran history.state om sparat. Annars topp.
|
|
268
|
+
const cachedScroll = history.state && typeof history.state.scrollY === 'number'
|
|
269
|
+
? history.state.scrollY : 0;
|
|
270
|
+
window.scrollTo( 0, cachedScroll );
|
|
271
|
+
} else {
|
|
272
|
+
window.scrollTo( 0, 0 );
|
|
273
|
+
}
|
|
274
|
+
moveFocusToMain();
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// Wrappa swap + VT i en Promise sa nasta nav vantar pa den.
|
|
278
|
+
let swapResolve;
|
|
279
|
+
inFlightSwap = new Promise( function ( r ) { swapResolve = r; } );
|
|
280
|
+
|
|
281
|
+
// Sprint J.4: skip VT vid month-change. VT-snapshot doljer
|
|
282
|
+
// original DOM under fade-tid, vilket blockerar hero-roll-
|
|
283
|
+
// animation. Vid month-change vill vi att rollers ska borja
|
|
284
|
+
// rulla omedelbart - skip VT ger detta. VT behalls for andra
|
|
285
|
+
// nav-byten dar cross-fade ar vardefull (Hem -> Kategorier etc).
|
|
286
|
+
const skipVT = isMonthChangeNav( fromUrl, finalUrl );
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
if ( typeof document.startViewTransition === 'function' && ! skipVT ) {
|
|
290
|
+
const transition = document.startViewTransition( swap );
|
|
291
|
+
try { await transition.finished; } catch ( _ ) { /* ignore */ }
|
|
292
|
+
} else {
|
|
293
|
+
swap();
|
|
294
|
+
}
|
|
295
|
+
} finally {
|
|
296
|
+
if ( inFlightSwap && swapResolve ) swapResolve();
|
|
297
|
+
inFlightSwap = null;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if ( ! options.popstate ) {
|
|
301
|
+
history.pushState( mergeState( { scrollY: 0 } ), '', finalUrl );
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Notify subscribers (nav-optimistic.js, hero-roll.js, future modules).
|
|
305
|
+
document.dispatchEvent( new CustomEvent( 'turbo:navigated', {
|
|
306
|
+
detail: { url: finalUrl, fromUrl: fromUrl, popstate: !! options.popstate },
|
|
307
|
+
} ) );
|
|
308
|
+
} catch ( err ) {
|
|
309
|
+
if ( err.name === 'AbortError' ) return;
|
|
310
|
+
// Sprint I.1: toast for synlighet innan vi gor full document-load
|
|
311
|
+
// fallback. Anvandaren far visuell feedback att natet failade.
|
|
312
|
+
if ( window.showToast ) {
|
|
313
|
+
try { window.showToast( 'Natverksfel - laddar om sidan.', 'error', 1800 ); } catch ( _ ) {}
|
|
314
|
+
}
|
|
315
|
+
// Fallback: full document-load. Browsern visar offline-page om
|
|
316
|
+
// SW har den cachad.
|
|
317
|
+
window.location.href = url;
|
|
318
|
+
} finally {
|
|
319
|
+
if ( myController === currentController ) currentController = null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/*--------------------------------------------------------------
|
|
324
|
+
Click-delegation: lyssna pa <a>-klick globalt. Kor INNAN nav-
|
|
325
|
+
optimistic.js pa samma click sa active-flytten visas direkt
|
|
326
|
+
medan turbo-fetchen pagar i bakgrunden.
|
|
327
|
+
--------------------------------------------------------------*/
|
|
328
|
+
document.addEventListener( 'click', function ( e ) {
|
|
329
|
+
if ( isModifierClick( e ) ) return;
|
|
330
|
+
const a = e.target.closest( 'a[href]' );
|
|
331
|
+
if ( ! a ) return;
|
|
332
|
+
if ( ! isInternalLink( a ) ) return;
|
|
333
|
+
// Sheet-trigger eller annan delegation-handler kan ha redan
|
|
334
|
+
// preventDefault:at - skippa i sa fall.
|
|
335
|
+
if ( e.defaultPrevented ) return;
|
|
336
|
+
e.preventDefault();
|
|
337
|
+
navigateTo( a.href );
|
|
338
|
+
} );
|
|
339
|
+
|
|
340
|
+
/*--------------------------------------------------------------
|
|
341
|
+
Back/forward via popstate. Initial pageload markeras med
|
|
342
|
+
turbo: true via mergeState sa popstate-handling vet att vi ar
|
|
343
|
+
i turbo-modell hela vagen. Browser-internals (scroll-cache,
|
|
344
|
+
etc.) bevaras eftersom vi merge:ar istallet for replace:ar.
|
|
345
|
+
--------------------------------------------------------------*/
|
|
346
|
+
window.addEventListener( 'popstate', function () {
|
|
347
|
+
navigateTo( window.location.href, { popstate: true } );
|
|
348
|
+
} );
|
|
349
|
+
|
|
350
|
+
// Initial state: merga in turbo-flag + spara forsta scrollY (0)
|
|
351
|
+
// utan att radera browser-cachade falt.
|
|
352
|
+
history.replaceState( mergeState( { scrollY: window.scrollY || 0 } ), '', window.location.href );
|
|
353
|
+
} )();
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@klodd/ds",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Klodd Design System - shared tokens, typography, and
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Klodd Design System - shared tokens, typography, components and JS for Jubb, Ekonom, and future apps. v2.0 inkluderar all komponentkod och delad JS - app-repona haller bara data och affarslogik.",
|
|
5
5
|
"main": "css/index.css",
|
|
6
6
|
"files": [
|
|
7
|
-
"css/"
|
|
7
|
+
"css/",
|
|
8
|
+
"js/"
|
|
8
9
|
],
|
|
9
10
|
"keywords": [
|
|
10
11
|
"design-system",
|