@alexandregme/zljs 1.18.0 → 1.19.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/CHANGELOG.md CHANGED
@@ -8,6 +8,39 @@ A change that needs action in an app has a **Migration** note. When updating, re
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [1.19.0] - 2026-11-02
12
+
13
+ ### Added
14
+
15
+ - `label` on `Spinner`: the name screen readers announce, `Loading` by default
16
+
17
+ ### Changed
18
+
19
+ - `Spinner` is a status with a name (`role="status"`) and has no color of its own. It was always white, and now inherits the color from around it
20
+ - `Loader` draws its spinner in the `primary` color, which holds 3:1 over the overlay on a white page. It was white, at 1.6:1. The `status` role moved from the overlay to the spinner, which takes the `label`
21
+
22
+ #### Migration
23
+
24
+ Search the app for `<Spinner`. On a dark surface, set a light text color around it, such as `text-white`. Remove a `role="status"` the app put around a `Spinner`, so there aren't two. `Loader` needs no change.
25
+
26
+ ### Fixed
27
+
28
+ - `Loader` covers the whole page. It had no position of its own, so it started where it was rendered, below anything before it
29
+
30
+ ## [1.18.1] - 2026-11-02
31
+
32
+ ### Removed
33
+
34
+ - Parameters in the hash, in `splitURLasPath` and the `query` of `useRouterStore`: `/orders#id=7` now returns `{}`
35
+
36
+ #### Migration
37
+
38
+ Search the app for `splitURLasPath` and `setRoute`. A URL with its parameters after `#` now reads them from `window.location.hash`.
39
+
40
+ ### Fixed
41
+
42
+ - `splitURLasPath` and the `query` of `useRouterStore` lost the query when the URL also had a hash: `/orders?id=7#top` returned `{ top: "" }` and now returns `{ id: "7" }`
43
+
11
44
  ## [1.18.0] - 2026-11-02
12
45
 
13
46
  ### Added
@@ -249,7 +282,9 @@ Replace the shade with the class of the `color` being tested, for example `/(^|\
249
282
 
250
283
  The message of `Error` is `text-zl-danger`. `none` and `ghost` didn't change.
251
284
 
252
- [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.18.0...HEAD
285
+ [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.19.0...HEAD
286
+ [1.19.0]: https://github.com/alexandregme/zljs/compare/v1.18.1...v1.19.0
287
+ [1.18.1]: https://github.com/alexandregme/zljs/compare/v1.18.0...v1.18.1
253
288
  [1.18.0]: https://github.com/alexandregme/zljs/compare/v1.17.0...v1.18.0
254
289
  [1.17.0]: https://github.com/alexandregme/zljs/compare/v1.16.0...v1.17.0
255
290
  [1.16.0]: https://github.com/alexandregme/zljs/compare/v1.15.0...v1.16.0
@@ -124,14 +124,22 @@ var Heading = ({ children, level = 1, color }) => {
124
124
  return /* @__PURE__ */ jsx3(Tag, { className: heading({ level, color }), children });
125
125
  };
126
126
 
127
- // core/state/toast/toast.store.ts
127
+ // core/state/zustand/toast/toast.store.ts
128
128
  import { create } from "zustand";
129
129
  import { devtools } from "zustand/middleware";
130
+
131
+ // core/state/zustand/toast/toast.const.ts
132
+ var toastInitialState = {
133
+ toasts: []
134
+ };
135
+ var toastDevtools = { name: "zljs", store: "toast" };
136
+
137
+ // core/state/zustand/toast/toast.store.ts
130
138
  var toastId = 0;
131
139
  var useToastStore = create()(
132
140
  devtools(
133
141
  (set, get) => ({
134
- toasts: [],
142
+ ...toastInitialState,
135
143
  addToast: (message, type = "error") => {
136
144
  const id = ++toastId;
137
145
  set(
@@ -151,7 +159,7 @@ var useToastStore = create()(
151
159
  info: (message) => get().addToast(message, "info"),
152
160
  warning: (message) => get().addToast(message, "warning")
153
161
  }),
154
- { name: "zljs", store: "toast" }
162
+ toastDevtools
155
163
  )
156
164
  );
157
165
 
@@ -187,14 +195,22 @@ var Toaster = () => {
187
195
  // core/toaster/index.ts
188
196
  import { toast as toast2 } from "sonner";
189
197
 
190
- // core/state/app/app.store.ts
198
+ // core/state/zustand/app/app.store.ts
191
199
  import { create as create2 } from "zustand";
192
200
  import { devtools as devtools2 } from "zustand/middleware";
201
+
202
+ // core/state/zustand/app/app.const.ts
203
+ var appInitialState = {
204
+ fetchingCalls: 0,
205
+ fetching: false
206
+ };
207
+ var appDevtools = { name: "zljs", store: "app" };
208
+
209
+ // core/state/zustand/app/app.store.ts
193
210
  var useAppStore = create2()(
194
211
  devtools2(
195
212
  (set) => ({
196
- fetchingCalls: 0,
197
- fetching: false,
213
+ ...appInitialState,
198
214
  startFetching: () => set(
199
215
  (s) => {
200
216
  const fetchingCalls = s.fetchingCalls + 1;
@@ -212,15 +228,15 @@ var useAppStore = create2()(
212
228
  "finishFetching"
213
229
  )
214
230
  }),
215
- { name: "zljs", store: "app" }
231
+ appDevtools
216
232
  )
217
233
  );
218
234
 
219
- // core/redux/redux-provider/redux-provider.tsx
235
+ // core/state/redux/redux-provider/redux-provider.tsx
220
236
  import { useState } from "react";
221
237
  import { Provider } from "react-redux";
222
238
 
223
- // core/redux/store/store.ts
239
+ // core/state/redux/store/store.ts
224
240
  import {
225
241
  combineReducers,
226
242
  configureStore
@@ -249,7 +265,7 @@ var createReduxStore = ({
249
265
  return store;
250
266
  };
251
267
 
252
- // core/redux/redux-provider/redux-provider.tsx
268
+ // core/state/redux/redux-provider/redux-provider.tsx
253
269
  import { jsx as jsx5 } from "react/jsx-runtime";
254
270
  var ReduxProvider = ({
255
271
  children,
@@ -269,53 +285,60 @@ var ReduxProvider = ({
269
285
  return /* @__PURE__ */ jsx5(Provider, { store, children });
270
286
  };
271
287
 
272
- // core/state/router/router.utils.ts
288
+ // core/state/zustand/router/router.utils.ts
273
289
  var splitURLasPath = (urlAsPath) => {
274
- let queryWithoutPath = "";
275
- if (urlAsPath?.indexOf("?") >= 0) {
276
- const [, query] = urlAsPath.split("?");
277
- queryWithoutPath = query ?? "";
278
- }
279
- if (urlAsPath?.indexOf("#") >= 0) {
280
- const [, query] = urlAsPath.split("#");
281
- queryWithoutPath = query ?? "";
282
- }
290
+ const [pathAndQuery = ""] = urlAsPath?.split("#") ?? [];
291
+ const [, query = ""] = pathAndQuery.split("?");
283
292
  const parametersAsObject = {};
284
- if (queryWithoutPath.length > 0) {
285
- queryWithoutPath.split("&").forEach((p) => {
286
- const [parameter, value] = p.split("=");
287
- if (parameter) {
288
- parametersAsObject[parameter] = value ?? "";
289
- }
290
- });
291
- }
293
+ query.split("&").forEach((p) => {
294
+ const [parameter, value] = p.split("=");
295
+ if (parameter) {
296
+ parametersAsObject[parameter] = value ?? "";
297
+ }
298
+ });
292
299
  return parametersAsObject;
293
300
  };
294
301
 
295
- // core/state/router/router.store.ts
302
+ // core/state/zustand/router/router.store.ts
296
303
  import { create as create3 } from "zustand";
297
304
  import { devtools as devtools3 } from "zustand/middleware";
305
+
306
+ // core/state/zustand/router/router.const.ts
307
+ var routerInitialState = {
308
+ urlAsPath: "/",
309
+ query: {}
310
+ };
311
+ var routerDevtools = { name: "zljs", store: "router" };
312
+
313
+ // core/state/zustand/router/router.store.ts
298
314
  var useRouterStore = create3()(
299
315
  devtools3(
300
316
  (set) => ({
301
- urlAsPath: "/",
302
- query: {},
317
+ ...routerInitialState,
303
318
  setRoute: (urlAsPath) => set({ urlAsPath, query: splitURLasPath(urlAsPath) }, false, "setRoute")
304
319
  }),
305
- { name: "zljs", store: "router" }
320
+ routerDevtools
306
321
  )
307
322
  );
308
323
 
309
- // core/state/page/page.store.ts
324
+ // core/state/zustand/page/page.store.ts
310
325
  import { create as create4 } from "zustand";
311
326
  import { devtools as devtools4 } from "zustand/middleware";
327
+
328
+ // core/state/zustand/page/page.const.ts
329
+ var pageInitialState = {
330
+ title: ""
331
+ };
332
+ var pageDevtools = { name: "zljs", store: "page" };
333
+
334
+ // core/state/zustand/page/page.store.ts
312
335
  var usePageStore = create4()(
313
336
  devtools4(
314
337
  (set) => ({
315
- title: "",
338
+ ...pageInitialState,
316
339
  setTitle: (title) => set({ title }, false, "setTitle")
317
340
  }),
318
- { name: "zljs", store: "page" }
341
+ pageDevtools
319
342
  )
320
343
  );
321
344
 
@@ -329,17 +352,30 @@ var spinnerIcons = {
329
352
  // core/spinner/spinner.styles.ts
330
353
  import { tv as tv4 } from "tailwind-variants";
331
354
  var spinner = tv4({
332
- base: "inline-flex animate-spin text-white"
355
+ base: "inline-flex animate-spin"
333
356
  });
334
357
 
335
358
  // core/spinner/spinner.tsx
336
359
  import { jsx as jsx6 } from "react/jsx-runtime";
337
- var Spinner = ({ variant = "circle", size = "md" }) => /* @__PURE__ */ jsx6("span", { "data-testid": "spinner", className: spinner(), children: /* @__PURE__ */ jsx6(Icon, { name: spinnerIcons[variant], size }) });
360
+ var Spinner = ({
361
+ variant = "circle",
362
+ size = "md",
363
+ label = "Loading"
364
+ }) => /* @__PURE__ */ jsx6(
365
+ "span",
366
+ {
367
+ "data-testid": "spinner",
368
+ role: "status",
369
+ "aria-label": label,
370
+ className: spinner(),
371
+ children: /* @__PURE__ */ jsx6(Icon, { name: spinnerIcons[variant], size })
372
+ }
373
+ );
338
374
 
339
375
  // core/loader/loader.styles.ts
340
376
  import { tv as tv5 } from "tailwind-variants";
341
- var overlay = tv5({
342
- base: "flex fixed justify-center items-center w-full h-full bg-black/20 z-50"
377
+ var loader = tv5({
378
+ base: "flex fixed inset-0 justify-center items-center bg-black/20 text-zl-primary z-50"
343
379
  });
344
380
 
345
381
  // core/loader/loader.tsx
@@ -347,7 +383,7 @@ import { jsx as jsx7 } from "react/jsx-runtime";
347
383
  var Loader = ({ label = "Loading" }) => {
348
384
  const fetching = useAppStore((s) => s.fetching);
349
385
  if (!fetching) return null;
350
- return /* @__PURE__ */ jsx7("div", { role: "status", "aria-label": label, className: overlay(), children: /* @__PURE__ */ jsx7(Spinner, { size: "lg" }) });
386
+ return /* @__PURE__ */ jsx7("div", { className: loader(), children: /* @__PURE__ */ jsx7(Spinner, { size: "lg", label }) });
351
387
  };
352
388
 
353
389
  export {
package/dist/index.d.ts CHANGED
@@ -431,9 +431,10 @@ type SpinnerVariant = "circle" | "dots" | "refresh";
431
431
  interface SpinnerProps {
432
432
  variant?: SpinnerVariant;
433
433
  size?: Size;
434
+ label?: string;
434
435
  }
435
436
 
436
- declare const Spinner: ({ variant, size }: SpinnerProps) => react.JSX.Element;
437
+ declare const Spinner: ({ variant, size, label, }: SpinnerProps) => react.JSX.Element;
437
438
 
438
439
  interface LoaderProps {
439
440
  label?: string;
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  usePageStore,
13
13
  useRouterStore,
14
14
  useToastStore
15
- } from "./chunk-BYW2ZJKS.js";
15
+ } from "./chunk-O6UAZGBC.js";
16
16
  import {
17
17
  Error,
18
18
  FormInput,
@@ -977,13 +977,21 @@ var Sidebar = ({
977
977
  // core/index.ts
978
978
  import { toast } from "sonner";
979
979
 
980
- // core/state/modal/modal.store.ts
980
+ // core/state/zustand/modal/modal.store.ts
981
981
  import { create } from "zustand";
982
982
  import { devtools } from "zustand/middleware";
983
+
984
+ // core/state/zustand/modal/modal.const.ts
985
+ var modalInitialState = {
986
+ modals: []
987
+ };
988
+ var modalDevtools = { name: "zljs", store: "modal" };
989
+
990
+ // core/state/zustand/modal/modal.store.ts
983
991
  var useModalStore = create()(
984
992
  devtools(
985
993
  (set, get) => ({
986
- modals: [],
994
+ ...modalInitialState,
987
995
  openModal: (name) => set((s) => ({ modals: [...s.modals, { name }] }), false, "openModal"),
988
996
  openModalWithPayload: (name, payload) => set(
989
997
  (s) => ({ modals: [...s.modals, { name, payload }] }),
@@ -998,7 +1006,7 @@ var useModalStore = create()(
998
1006
  isOpen: (name) => get().modals.some((m) => m.name === name),
999
1007
  getPayload: (name) => get().modals.find((m) => m.name === name)?.payload
1000
1008
  }),
1001
- { name: "zljs", store: "modal" }
1009
+ modalDevtools
1002
1010
  )
1003
1011
  );
1004
1012
 
@@ -7,7 +7,7 @@ import {
7
7
  Toaster,
8
8
  usePageStore,
9
9
  useRouterStore
10
- } from "../chunk-BYW2ZJKS.js";
10
+ } from "../chunk-O6UAZGBC.js";
11
11
 
12
12
  // core/next/root-layout/root-layout.styles.ts
13
13
  import { tv } from "tailwind-variants";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexandregme/zljs",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "Opinionated, accessible React component library for enterprise apps (Next.js, Tailwind CSS v4).",
5
5
  "keywords": [
6
6
  "react",