@vygruppen/spor-react 13.5.0 → 13.7.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @vygruppen/spor-react@13.5.0 build /home/runner/work/spor/spor/packages/spor-react
2
+ > @vygruppen/spor-react@13.7.0 build /home/runner/work/spor/spor/packages/spor-react
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: src/index.tsx, src/icons/index.tsx
@@ -11,18 +11,18 @@ CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
13
  DTS Build start
14
- CJS dist/icons/index.cjs 381.00 B
15
- CJS dist/index.cjs 377.88 KB
16
- CJS dist/icons/index.cjs.map 157.00 B
17
- CJS dist/index.cjs.map 751.12 KB
18
- CJS ⚡️ Build success in 2931ms
19
- ESM dist/index.mjs 353.23 KB
14
+ ESM dist/index.mjs 356.08 KB
20
15
  ESM dist/icons/index.mjs 110.00 B
21
- ESM dist/index.mjs.map 751.12 KB
16
+ ESM dist/index.mjs.map 756.21 KB
22
17
  ESM dist/icons/index.mjs.map 157.00 B
23
- ESM ⚡️ Build success in 2932ms
24
- DTS ⚡️ Build success in 21320ms
18
+ ESM ⚡️ Build success in 2676ms
19
+ CJS dist/index.cjs 380.79 KB
20
+ CJS dist/icons/index.cjs 381.00 B
21
+ CJS dist/index.cjs.map 756.21 KB
22
+ CJS dist/icons/index.cjs.map 157.00 B
23
+ CJS ⚡️ Build success in 2678ms
24
+ DTS ⚡️ Build success in 21841ms
25
25
  DTS dist/icons/index.d.ts 44.00 B
26
- DTS dist/index.d.ts 154.92 KB
26
+ DTS dist/index.d.ts 156.17 KB
27
27
  DTS dist/icons/index.d.cts 44.00 B
28
- DTS dist/index.d.cts 154.92 KB
28
+ DTS dist/index.d.cts 156.17 KB
@@ -1,8 +1,8 @@
1
1
 
2
- > @vygruppen/spor-react@13.5.0 postinstall /home/runner/work/spor/spor/packages/spor-react
2
+ > @vygruppen/spor-react@13.7.0 postinstall /home/runner/work/spor/spor/packages/spor-react
3
3
  > chakra typegen src/theme/index.ts
4
4
 
5
- ◇ injected env (0) from .env // tip: encrypted .env [www.dotenvx.com]
5
+ ◇ injected env (0) from .env // tip: override existing { override: true }
6
6
  ┌ Chakra CLI ⚡️
7
7
  [?25l│
8
8
  ◒ Generating conditions types...
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @vygruppen/spor-react
2
2
 
3
+ ## 13.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b80fda2: Toast: Introduce "inverted" as a prop, that uses darkmode colors in lightmode, and lightmode colors in darkmode.
8
+ - a1d5a12: Autocomplete: add a size-prop that can be set to either 'md' or 'sm'.
9
+
10
+ ### Patch Changes
11
+
12
+ - e6bfa69: override safari autofill for input fields with spor colors
13
+ - 6d0bf57: TextLink: Add non-breaking space for external icon so that it never breaks over to a newline alone.
14
+ - 022e894: Separator: Change borderColor of the dashed separator to use the outline.default token
15
+ InputChip: Adjust the height of the different sizes to match with design.
16
+ TextLink: Change the ExternalLink-Icon to be of size 30x30 when TextLink is of size "lg"
17
+ - Updated dependencies [783c84f]
18
+ - @vygruppen/spor-design-tokens@5.1.1
19
+
20
+ ## 13.6.0
21
+
22
+ ### Minor Changes
23
+
24
+ - ce5b9e0: Add new VyTeknologi brand theme and deprecate VyUtvikling
25
+ - New `Brand.VyTeknologi` theme, usable with `<SporProvider theme={themes[Brand.VyTeknologi]}>`
26
+ - Three new color palettes with 12 steps each: `teal`, `pink` and `violet`, with named aliases (e.g. `grape` → `violet.900`, `moss` → `teal.700`, `jam` → `pink.800`)
27
+ - The existing `pink` alias (→ `red.50`) still resolves as before; the new range is available as `pink.50`–`pink.1100`
28
+ - `Brand.VyUtvikling` and `vyUtviklingColors` are marked as `@deprecated` — migrate to `Brand.VyTeknologi`
29
+ - The MCP server's `get_spor_tokens` tool now accepts `vyTeknologi` as a theme
30
+
31
+ ### Patch Changes
32
+
33
+ - Updated dependencies [ce5b9e0]
34
+ - @vygruppen/spor-design-tokens@5.1.0
35
+
3
36
  ## 13.5.0
4
37
 
5
38
  ### Minor Changes
@@ -0,0 +1,108 @@
1
+ import { render, screen, waitFor } from "@testing-library/react";
2
+ import userEvent from "@testing-library/user-event";
3
+ import { Button, createToast, SporProvider } from "@vygruppen/spor-react";
4
+ import { describe, expect, test, vi } from "vitest";
5
+
6
+ // SporProvider renders the Toaster internally, so toasts appear within it
7
+
8
+ describe("Toast", () => {
9
+ test("shows toast triggered by a button click", async () => {
10
+ const user = userEvent.setup();
11
+
12
+ render(
13
+ <SporProvider>
14
+ <Button
15
+ variant="secondary"
16
+ onClick={() =>
17
+ createToast({
18
+ variant: "success",
19
+ text: "Button triggered toast",
20
+ })
21
+ }
22
+ >
23
+ Show toast
24
+ </Button>
25
+ </SporProvider>,
26
+ );
27
+
28
+ expect(
29
+ screen.queryByText("Button triggered toast"),
30
+ ).not.toBeInTheDocument();
31
+
32
+ await user.click(screen.getByRole("button", { name: "Show toast" }));
33
+
34
+ await waitFor(() => {
35
+ expect(screen.getByText("Button triggered toast")).toBeInTheDocument();
36
+ });
37
+ });
38
+
39
+ test("close toast by a close trigger button click", async () => {
40
+ const user = userEvent.setup();
41
+
42
+ render(
43
+ <SporProvider>
44
+ <Button
45
+ variant="secondary"
46
+ onClick={() =>
47
+ createToast({
48
+ variant: "success",
49
+ text: "Button triggered toast 2",
50
+ duration: 10_000,
51
+ closable: true,
52
+ })
53
+ }
54
+ >
55
+ Show toast
56
+ </Button>
57
+ </SporProvider>,
58
+ );
59
+
60
+ expect(
61
+ screen.queryByText("Button triggered toast 2"),
62
+ ).not.toBeInTheDocument();
63
+
64
+ await user.click(screen.getByRole("button", { name: "Show toast" }));
65
+
66
+ await waitFor(() => {
67
+ expect(screen.getByText("Button triggered toast 2")).toBeInTheDocument();
68
+ });
69
+
70
+ await user.click(screen.getByRole("button", { name: "Lukk" }));
71
+ await new Promise((resolve) => setTimeout(resolve, 2000));
72
+ expect(
73
+ screen.queryByText("Button triggered toast 2"),
74
+ ).not.toBeInTheDocument();
75
+ });
76
+
77
+ test("click on custom action button in toast", async () => {
78
+ const user = userEvent.setup();
79
+ const onButtonClick = vi.fn();
80
+
81
+ render(
82
+ <SporProvider>
83
+ <Button
84
+ variant="secondary"
85
+ onClick={() =>
86
+ createToast({
87
+ variant: "success",
88
+ text: "Button triggered toast 3",
89
+ action: {
90
+ label: "Undo",
91
+ onClick: onButtonClick,
92
+ },
93
+ })
94
+ }
95
+ >
96
+ Show toast
97
+ </Button>
98
+ </SporProvider>,
99
+ );
100
+
101
+ await user.click(screen.getByRole("button", { name: "Show toast" }));
102
+ await waitFor(() => {
103
+ expect(screen.getByText("Button triggered toast 3")).toBeInTheDocument();
104
+ });
105
+ await user.click(screen.getByRole("button", { name: "Undo" }));
106
+ expect(onButtonClick).toHaveBeenCalled();
107
+ });
108
+ });
package/dist/index.cjs CHANGED
@@ -3304,10 +3304,29 @@ var texts14 = createTexts({
3304
3304
  var ExternalIcon = ({
3305
3305
  label,
3306
3306
  size
3307
- }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3308
- size === "lg" || size === "md" ? /* @__PURE__ */ jsxRuntime.jsx(spor_icon_react_star.LinkOutOutline24Icon, { "aria-hidden": true, display: "inline" }) : /* @__PURE__ */ jsxRuntime.jsx(spor_icon_react_star.LinkOutOutline18Icon, { "aria-hidden": true, display: "inline" }),
3309
- /* @__PURE__ */ jsxRuntime.jsx(react.VisuallyHidden, { children: label })
3310
- ] });
3307
+ }) => {
3308
+ const getIcon = () => {
3309
+ switch (size) {
3310
+ case "lg": {
3311
+ return /* @__PURE__ */ jsxRuntime.jsx(spor_icon_react_star.LinkOutOutline30Icon, { "aria-hidden": true, display: "inline" });
3312
+ }
3313
+ case "md": {
3314
+ return /* @__PURE__ */ jsxRuntime.jsx(spor_icon_react_star.LinkOutOutline24Icon, { "aria-hidden": true, display: "inline" });
3315
+ }
3316
+ case "sm": {
3317
+ return /* @__PURE__ */ jsxRuntime.jsx(spor_icon_react_star.LinkOutOutline18Icon, { "aria-hidden": true, display: "inline" });
3318
+ }
3319
+ default: {
3320
+ return /* @__PURE__ */ jsxRuntime.jsx(spor_icon_react_star.LinkOutOutline24Icon, { "aria-hidden": true, display: "inline" });
3321
+ }
3322
+ }
3323
+ };
3324
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { whiteSpace: "nowrap" }, children: [
3325
+ "\u2060",
3326
+ getIcon(),
3327
+ /* @__PURE__ */ jsxRuntime.jsx(react.VisuallyHidden, { children: label })
3328
+ ] });
3329
+ };
3311
3330
  var TextLink = ({
3312
3331
  ref,
3313
3332
  children,
@@ -3668,6 +3687,7 @@ function Autocomplete({
3668
3687
  openOnClick = true,
3669
3688
  openOnFocus = true,
3670
3689
  ref,
3690
+ size = "md",
3671
3691
  ...rest
3672
3692
  }) {
3673
3693
  const { contains } = react.useFilter({ sensitivity: "base" });
@@ -3726,7 +3746,8 @@ function Autocomplete({
3726
3746
  onFocus == null ? void 0 : onFocus(event);
3727
3747
  if (openOnFocus && filteredChildren.length > 0)
3728
3748
  combobox.setOpen(true);
3729
- }
3749
+ },
3750
+ size
3730
3751
  }
3731
3752
  ) }),
3732
3753
  /* @__PURE__ */ jsxRuntime.jsx(react.Combobox.IndicatorGroup, { children: /* @__PURE__ */ jsxRuntime.jsx(react.Combobox.ClearTrigger, { asChild: true, "aria-label": t(texts16.clearValue), children: /* @__PURE__ */ jsxRuntime.jsx(CloseButton, { size: "xs", tabIndex: 0 }) }) })
@@ -6684,6 +6705,7 @@ var fontFaces = `
6684
6705
  var Brand = /* @__PURE__ */ ((Brand2) => {
6685
6706
  Brand2["VyDigital"] = "VyDigital";
6686
6707
  Brand2["VyUtvikling"] = "VyUtvikling";
6708
+ Brand2["VyTeknologi"] = "VyTeknologi";
6687
6709
  Brand2["CargoNet"] = "CargoNet";
6688
6710
  return Brand2;
6689
6711
  })(Brand || {});
@@ -6698,31 +6720,38 @@ var createToast = ({
6698
6720
  duration = 6e3,
6699
6721
  width = "sm",
6700
6722
  action,
6701
- closable = false
6723
+ closable = false,
6724
+ inverted = false
6702
6725
  }) => toaster.create({
6703
6726
  description: text,
6704
6727
  type: variant,
6705
6728
  id: id ?? crypto.randomUUID(),
6706
6729
  duration,
6707
6730
  action,
6708
- meta: { width },
6731
+ meta: { width, inverted },
6709
6732
  closable
6710
6733
  });
6711
6734
  var Toaster = () => {
6712
6735
  return /* @__PURE__ */ jsxRuntime.jsx(react.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(react.Toaster, { toaster, insetInline: { mdDown: "4" }, children: (toast) => {
6713
- var _a6;
6736
+ var _a6, _b5;
6714
6737
  return /* @__PURE__ */ jsxRuntime.jsxs(
6715
6738
  react.Toast.Root,
6716
6739
  {
6717
6740
  width: { md: (_a6 = toast.meta) == null ? void 0 : _a6.width },
6718
- border: "sm",
6719
- borderColor: `outline.${toast.type}`,
6720
- boxShadow: "sm",
6741
+ "data-inverted": ((_b5 = toast.meta) == null ? void 0 : _b5.inverted) ? "" : void 0,
6721
6742
  role: "alert",
6722
6743
  children: [
6723
6744
  /* @__PURE__ */ jsxRuntime.jsx(AlertIcon, { variant: toast.type }),
6724
6745
  /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { gap: "1", flex: "1", maxWidth: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(react.Toast.Description, { children: toast.description }) }),
6725
- toast.action && /* @__PURE__ */ jsxRuntime.jsx(react.Toast.ActionTrigger, { onClick: toast.action.onClick, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "xs", children: toast.action.label }) }),
6746
+ toast.action && /* @__PURE__ */ jsxRuntime.jsx(react.Toast.ActionTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
6747
+ Button,
6748
+ {
6749
+ variant: "ghost",
6750
+ size: "xs",
6751
+ onClick: toast.action.onClick,
6752
+ children: toast.action.label
6753
+ }
6754
+ ) }),
6726
6755
  toast.closable && /* @__PURE__ */ jsxRuntime.jsx(react.Toast.CloseTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(CloseButton, { size: "xs" }) })
6727
6756
  ]
6728
6757
  }
@@ -7394,6 +7423,10 @@ var inputRecipe = react.defineRecipe({
7394
7423
  _focus: {
7395
7424
  outline: "2px solid",
7396
7425
  outlineColor: "outline.focus"
7426
+ },
7427
+ "&:-webkit-autofill, &:-webkit-autofill:focus": {
7428
+ boxShadow: "0 0 0 1000px var(--spor-colors-surface-info-hover) inset",
7429
+ WebkitTextFillColor: "var(--spor-colors-text)"
7397
7430
  }
7398
7431
  },
7399
7432
  floating: {
@@ -7413,6 +7446,10 @@ var inputRecipe = react.defineRecipe({
7413
7446
  focus: {
7414
7447
  outline: "1px solid",
7415
7448
  outlineColor: "outline.focus"
7449
+ },
7450
+ "&:-webkit-autofill, &:-webkit-autofill:focus": {
7451
+ boxShadow: "0 0 0 1000px var(--spor-colors-surface-info-hover) inset",
7452
+ WebkitTextFillColor: "var(--spor-colors-text)"
7416
7453
  }
7417
7454
  }
7418
7455
  },
@@ -7586,13 +7623,14 @@ var separatorRecipe = react.defineRecipe({
7586
7623
  borderStyle: "solid"
7587
7624
  },
7588
7625
  dashed: {
7626
+ "--dash-color": "var(--spor-colors-outline)",
7589
7627
  borderImageSlice: 1,
7590
7628
  borderImageSource: `repeating-linear-gradient(
7591
7629
  var(--gradient-direction),
7592
- var(--spor-colors-outline-disabled) 0,
7593
- var(--spor-colors-outline-disabled) var(--dash-size),
7630
+ var(--dash-color) 0,
7631
+ var(--dash-color) var(--dash-size),
7594
7632
  transparent var(--dash-size),
7595
- transparent calc(var(--dash-size) + var(--dash-gap))
7633
+ transparent calc(var(--dash-size) + var(--dash-gap))
7596
7634
  )`
7597
7635
  }
7598
7636
  },
@@ -7776,6 +7814,9 @@ var vyDigitalColors = react.defineSemanticTokens.colors({
7776
7814
  var vyUtviklingColors = react.defineSemanticTokens.colors({
7777
7815
  ...tokens4__default.default.color["vy-utvikling"].color.vyUtvikling
7778
7816
  });
7817
+ var vyTeknologiColors = react.defineSemanticTokens.colors({
7818
+ ...tokens4__default.default.color["vy-teknologi"].color.vyTeknologi
7819
+ });
7779
7820
  var cargonetColors = react.defineSemanticTokens.colors({
7780
7821
  ...tokens4__default.default.color["cargonet"].color.cargonet
7781
7822
  });
@@ -7822,6 +7863,10 @@ var semanticTokens = {
7822
7863
  ...baseSemanticTokens,
7823
7864
  colors: vyUtviklingColors
7824
7865
  },
7866
+ ["VyTeknologi" /* VyTeknologi */]: {
7867
+ ...baseSemanticTokens,
7868
+ colors: vyTeknologiColors
7869
+ },
7825
7870
  ["CargoNet" /* CargoNet */]: {
7826
7871
  ...baseSemanticTokens,
7827
7872
  colors: cargonetColors
@@ -10359,7 +10404,7 @@ var inputChipSlotRecipe = react.defineSlotRecipe({
10359
10404
  root: {
10360
10405
  fontSize: "desktop.xs",
10361
10406
  paddingX: "1.5",
10362
- paddingY: "0",
10407
+ height: 5,
10363
10408
  fontWeight: "normal",
10364
10409
  borderRadius: "xs"
10365
10410
  }
@@ -10368,17 +10413,16 @@ var inputChipSlotRecipe = react.defineSlotRecipe({
10368
10413
  root: {
10369
10414
  fontSize: "desktop.sm",
10370
10415
  paddingX: "2",
10371
- paddingY: "0.5",
10416
+ height: 6,
10372
10417
  fontWeight: "bold",
10373
10418
  borderRadius: "9px"
10374
10419
  }
10375
10420
  },
10376
10421
  md: {
10377
10422
  root: {
10378
- padding: 5,
10379
10423
  fontSize: "desktop.md",
10380
10424
  paddingX: "2",
10381
- paddingY: "1",
10425
+ height: 7,
10382
10426
  fontWeight: "bold",
10383
10427
  borderRadius: "sm"
10384
10428
  }
@@ -10387,7 +10431,7 @@ var inputChipSlotRecipe = react.defineSlotRecipe({
10387
10431
  root: {
10388
10432
  fontSize: "desktop.md",
10389
10433
  paddingX: "2",
10390
- paddingY: "3",
10434
+ height: "8",
10391
10435
  fontWeight: "bold",
10392
10436
  borderRadius: "md"
10393
10437
  }
@@ -12284,6 +12328,7 @@ var toastSlotRecipe = react.defineSlotRecipe({
12284
12328
  translate: "var(--x) var(--y)",
12285
12329
  opacity: "var(--opacity)",
12286
12330
  willChange: "translate, opacity, scale",
12331
+ outline: "1px solid",
12287
12332
  borderRadius: "sm",
12288
12333
  transition: "translate 400ms, scale 400ms, opacity 400ms, height 400ms, box-shadow 200ms",
12289
12334
  transitionTimingFunction: "cubic-bezier(0.21, 1.02, 0.73, 1)",
@@ -12291,16 +12336,52 @@ var toastSlotRecipe = react.defineSlotRecipe({
12291
12336
  transition: "translate 400ms, scale 400ms, opacity 200ms",
12292
12337
  transitionTimingFunction: "cubic-bezier(0.06, 0.71, 0.55, 1)"
12293
12338
  },
12294
- boxShadow: "xl",
12339
+ boxShadow: "sm",
12295
12340
  color: "text",
12296
12341
  "&[data-type=success]": {
12297
- backgroundColor: "surface.success"
12342
+ backgroundColor: "surface.success",
12343
+ outlineColor: "outline.success"
12298
12344
  },
12299
12345
  "&[data-type=error]": {
12300
- backgroundColor: "surface.critical"
12346
+ backgroundColor: "surface.critical",
12347
+ outlineColor: "outline.critical"
12301
12348
  },
12302
12349
  "&[data-type=info]": {
12303
- backgroundColor: "surface.info"
12350
+ backgroundColor: "surface.info",
12351
+ outlineColor: "outline.info"
12352
+ },
12353
+ "&[data-inverted][data-type=success]": {
12354
+ backgroundColor: { _light: "darkTeal", _dark: "seaMist" },
12355
+ color: { _light: "mint", _dark: "jungle" },
12356
+ outlineColor: { _light: "greenHaze", _dark: "coralGreen" },
12357
+ "& path:first-of-type": {
12358
+ fill: { _light: "mint", _dark: "jungle" }
12359
+ },
12360
+ "& path:not(:first-of-type)": {
12361
+ fill: { _light: "darkTeal", _dark: "seaMist" }
12362
+ }
12363
+ },
12364
+ "&[data-inverted][data-type=error]": {
12365
+ backgroundColor: { _light: "burgundy", _dark: "lightRed" },
12366
+ color: { _light: "pink", _dark: "maroon" },
12367
+ outlineColor: { _light: "crimson", _dark: "salmon" },
12368
+ "& path:first-of-type": {
12369
+ fill: { _light: "pink", _dark: "maroon" }
12370
+ },
12371
+ "& path:not(:first-of-type)": {
12372
+ fill: { _light: "burgundy", _dark: "lightRed" }
12373
+ }
12374
+ },
12375
+ "&[data-inverted][data-type=info]": {
12376
+ backgroundColor: { _light: "darkBlue", _dark: "lightBlue" },
12377
+ color: { _light: "icyBlue", _dark: "royal" },
12378
+ outlineColor: { _light: "ocean", _dark: "cloudy" },
12379
+ "& path:first-of-type": {
12380
+ fill: { _light: "icyBlue", _dark: "navy" }
12381
+ },
12382
+ "& path:not(:first-of-type)": {
12383
+ fill: { _light: "darkBlue", _dark: "lightBlue" }
12384
+ }
12304
12385
  }
12305
12386
  },
12306
12387
  title: {
@@ -13174,6 +13255,10 @@ var themes = {
13174
13255
  ["VyUtvikling" /* VyUtvikling */]: react.createSystem(
13175
13256
  react.defaultBaseConfig,
13176
13257
  generateTheme("VyUtvikling" /* VyUtvikling */)
13258
+ ),
13259
+ ["VyTeknologi" /* VyTeknologi */]: react.createSystem(
13260
+ react.defaultBaseConfig,
13261
+ generateTheme("VyTeknologi" /* VyTeknologi */)
13177
13262
  )
13178
13263
  };
13179
13264
  var system = themes["VyDigital" /* VyDigital */];