@synerise/ds-switch 1.2.32 → 1.2.33

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
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.2.33](https://github.com/synerise/synerise-design/compare/@synerise/ds-switch@1.2.32...@synerise/ds-switch@1.2.33) (2026-06-17)
7
+
8
+ **Note:** Version bump only for package @synerise/ds-switch
9
+
6
10
  ## [1.2.32](https://github.com/synerise/synerise-design/compare/@synerise/ds-switch@1.2.31...@synerise/ds-switch@1.2.32) (2026-06-11)
7
11
 
8
12
  **Note:** Version bump only for package @synerise/ds-switch
@@ -0,0 +1,17 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * DS-native bare toggle (antd-free replacement for the former `RawSwitch = antd Switch`). Renders a
4
+ * `<button role="switch">` — keyboard (space/enter) toggling works natively. Controlled via `checked`,
5
+ * uncontrolled via `defaultChecked`. Native button attributes + `data-*` are forwarded so React-Final-Form
6
+ * `{...input}` spreads keep working. The `ds-switch-*` / `ant-switch-*` class hooks are kept on the element
7
+ * (the `ant-*` ones temporarily, for ui-tests / external CSS).
8
+ */
9
+ declare const RawSwitch: React.ForwardRefExoticComponent<Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type" | "onChange" | "onClick" | "value"> & {
10
+ checked?: boolean;
11
+ defaultChecked?: boolean;
12
+ loading?: boolean;
13
+ size?: import('./Switch.types').SwitchSize;
14
+ onChange?: import('./Switch.types').SwitchChangeHandler;
15
+ onClick?: import('./Switch.types').SwitchChangeHandler;
16
+ } & import('@synerise/ds-utils').DataAttributes & React.RefAttributes<HTMLButtonElement>>;
17
+ export default RawSwitch;
@@ -0,0 +1,40 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import classNames from "classnames";
3
+ import { forwardRef, useState } from "react";
4
+ import { Toggle, Handle, Spinner } from "./RawSwitch.styles.js";
5
+ const RawSwitch = forwardRef(({
6
+ checked,
7
+ defaultChecked,
8
+ disabled,
9
+ loading,
10
+ size: _size,
11
+ className,
12
+ onChange,
13
+ onClick,
14
+ ...rest
15
+ }, ref) => {
16
+ const isControlled = checked !== void 0;
17
+ const [internalChecked, setInternalChecked] = useState(Boolean(defaultChecked));
18
+ const isChecked = isControlled ? Boolean(checked) : internalChecked;
19
+ const isDisabled = Boolean(disabled || loading);
20
+ const hasError = (className ?? "").split(/\s+/).includes("error");
21
+ const handleClick = (event) => {
22
+ if (isDisabled) {
23
+ return;
24
+ }
25
+ const next = !isChecked;
26
+ if (!isControlled) {
27
+ setInternalChecked(next);
28
+ }
29
+ onClick?.(next, event);
30
+ onChange?.(next, event);
31
+ };
32
+ return /* @__PURE__ */ jsx(Toggle, { ...rest, ref, type: "button", role: "switch", "aria-checked": isChecked, disabled: isDisabled, $checked: isChecked, $error: hasError, $loading: loading, onClick: handleClick, className: classNames("ant-switch ds-switch-toggle", {
33
+ "ant-switch-checked ds-switch-checked": isChecked,
34
+ "ant-switch-disabled ds-switch-disabled": isDisabled,
35
+ "ant-switch-loading ds-switch-loading": loading
36
+ }, className), children: /* @__PURE__ */ jsx(Handle, { $checked: isChecked, children: loading && /* @__PURE__ */ jsx(Spinner, {}) }) });
37
+ });
38
+ export {
39
+ RawSwitch as default
40
+ };
@@ -0,0 +1,11 @@
1
+ type ToggleProps = {
2
+ $checked?: boolean;
3
+ $error?: boolean;
4
+ $loading?: boolean;
5
+ };
6
+ export declare const Toggle: import('styled-components').StyledComponent<"button", any, ToggleProps, never>;
7
+ export declare const Handle: import('styled-components').StyledComponent<"span", any, {
8
+ $checked?: boolean;
9
+ }, never>;
10
+ export declare const Spinner: import('styled-components').StyledComponent<"span", any, {}, never>;
11
+ export {};
@@ -0,0 +1,33 @@
1
+ import styled, { css, keyframes } from "styled-components";
2
+ const trackBackground = (props, hovered) => {
3
+ const {
4
+ theme,
5
+ $checked,
6
+ $error
7
+ } = props;
8
+ if ($error) {
9
+ return theme.palette["red-600"];
10
+ }
11
+ if ($checked) {
12
+ return theme.palette[hovered ? "green-500" : "green-600"];
13
+ }
14
+ return theme.palette[hovered ? "grey-500" : "grey-400"];
15
+ };
16
+ const spin = /* @__PURE__ */ keyframes(["from{transform:rotate(0deg);}to{transform:rotate(360deg);}"]);
17
+ const Toggle = /* @__PURE__ */ styled.button.withConfig({
18
+ displayName: "RawSwitchstyles__Toggle",
19
+ componentId: "sc-1ducz2x-0"
20
+ })(["position:relative;box-sizing:border-box;min-width:28px;width:28px;height:16px;padding:0;border:2px solid transparent;border-radius:8px;background-color:", ";cursor:pointer;vertical-align:middle;outline:none;transition:background-color 0.2s ease,border-color 0.2s ease;&:hover:not(:disabled){background-color:", ";}&:focus-visible{border-color:", ";}&:disabled{cursor:not-allowed;opacity:0.4;}", ""], (props) => trackBackground(props, false), (props) => trackBackground(props, true), (props) => props.theme.palette["blue-600"], (props) => !!props.$loading && css(["cursor:default;"]));
21
+ const Handle = /* @__PURE__ */ styled.span.withConfig({
22
+ displayName: "RawSwitchstyles__Handle",
23
+ componentId: "sc-1ducz2x-1"
24
+ })(["position:absolute;top:0;left:", ";width:12px;height:12px;border-radius:50%;background-color:", ";transition:left 0.2s ease;"], (props) => props.$checked ? "calc(100% - 12px)" : "0", (props) => props.theme.palette.white);
25
+ const Spinner = /* @__PURE__ */ styled.span.withConfig({
26
+ displayName: "RawSwitchstyles__Spinner",
27
+ componentId: "sc-1ducz2x-2"
28
+ })(["position:absolute;top:1px;left:1px;width:10px;height:10px;border:1.5px solid ", ";border-top-color:", ";border-radius:50%;animation:", " 0.8s linear infinite;"], (props) => props.theme.palette["grey-400"], (props) => props.theme.palette["green-600"], spin);
29
+ export {
30
+ Handle,
31
+ Spinner,
32
+ Toggle
33
+ };
package/dist/Switch.d.ts CHANGED
@@ -1,13 +1,21 @@
1
1
  import { default as React } from 'react';
2
- export declare const RawSwitch: React.ForwardRefExoticComponent<import('antd').SwitchProps & React.RefAttributes<HTMLElement>>;
3
- export declare const Switch: React.ForwardRefExoticComponent<Omit<import('antd').SwitchProps, "size"> & {
4
- errorText?: React.ReactNode;
2
+ import { default as RawSwitch } from './RawSwitch';
3
+ export { RawSwitch };
4
+ export declare const Switch: React.ForwardRefExoticComponent<Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type" | "onChange" | "onClick" | "value"> & {
5
+ checked?: boolean;
6
+ defaultChecked?: boolean;
7
+ loading?: boolean;
8
+ size?: import('./Switch.types').SwitchSize;
9
+ onChange?: import('./Switch.types').SwitchChangeHandler;
10
+ onClick?: import('./Switch.types').SwitchChangeHandler;
11
+ } & import('@synerise/ds-utils').DataAttributes & {
5
12
  label: React.ReactNode;
6
13
  description?: React.ReactNode;
14
+ errorText?: React.ReactNode;
7
15
  withFormElementMargin?: boolean;
8
- } & {
9
16
  tooltipIcon?: React.ReactNode;
10
17
  tooltip?: React.ReactNode;
11
18
  tooltipConfig?: import('@synerise/ds-tooltip').TooltipProps;
19
+ style?: React.CSSProperties;
12
20
  } & React.RefAttributes<HTMLDivElement>>;
13
21
  export default Switch;
package/dist/Switch.js CHANGED
@@ -1,10 +1,8 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { Switch as Switch$1 } from "antd";
3
- import classnames from "classnames";
2
+ import classNames from "classnames";
4
3
  import { forwardRef, useId, useRef } from "react";
4
+ import RawSwitch from "./RawSwitch.js";
5
5
  import { SwitchWrapper, LabelSwitchWrapper, Texts, Label, DescriptionWrapper, BelowLabel, Error, Description } from "./Switch.styles.js";
6
- import "./style/index.css";
7
- const RawSwitch = Switch$1;
8
6
  const Switch = forwardRef(({
9
7
  errorText,
10
8
  label,
@@ -15,13 +13,13 @@ const Switch = forwardRef(({
15
13
  tooltip,
16
14
  className,
17
15
  tooltipConfig,
18
- ...antdSwitchProps
16
+ ...rawSwitchProps
19
17
  }, ref) => {
20
18
  const id = useId();
21
19
  const switchElement = useRef(null);
22
- return /* @__PURE__ */ jsxs(SwitchWrapper, { ref, className: classnames(["ds-switch", className]), formElementMargin: Boolean(withFormElementMargin), children: [
20
+ return /* @__PURE__ */ jsxs(SwitchWrapper, { ref, className: classNames(["ds-switch", className]), formElementMargin: Boolean(withFormElementMargin), children: [
23
21
  /* @__PURE__ */ jsxs(LabelSwitchWrapper, { children: [
24
- /* @__PURE__ */ jsx(RawSwitch, { ...antdSwitchProps, size: "small", className: errorText ? "error" : "", id, ref: switchElement, onChange: (checked, event) => {
22
+ /* @__PURE__ */ jsx(RawSwitch, { ...rawSwitchProps, size: "small", className: errorText ? "error" : "", id, ref: switchElement, onChange: (checked, event) => {
25
23
  setTimeout(() => {
26
24
  if (switchElement !== null && switchElement.current !== null) {
27
25
  switchElement.current.blur();
@@ -1,6 +1,7 @@
1
1
  import styled from "styled-components";
2
2
  import { FormFieldLabel } from "@synerise/ds-form-field";
3
3
  import { macro } from "@synerise/ds-typography";
4
+ import { Toggle } from "./RawSwitch.styles.js";
4
5
  const SwitchWrapper = /* @__PURE__ */ styled.div.withConfig({
5
6
  displayName: "Switchstyles__SwitchWrapper",
6
7
  componentId: "sc-1gmh4sk-0"
@@ -12,7 +13,7 @@ const Texts = /* @__PURE__ */ styled.div.withConfig({
12
13
  const Label = /* @__PURE__ */ styled(FormFieldLabel).withConfig({
13
14
  displayName: "Switchstyles__Label",
14
15
  componentId: "sc-1gmh4sk-2"
15
- })(["", ";cursor:pointer;transition:0.3s ease;width:100%;display:flex;align-items:center;"], macro.heading);
16
+ })(["", ";color:", ";cursor:pointer;transition:0.3s ease;width:100%;display:flex;align-items:center;"], macro.heading, (props) => props.theme.palette["grey-700"]);
16
17
  const BelowLabel = /* @__PURE__ */ styled.div.withConfig({
17
18
  displayName: "Switchstyles__BelowLabel",
18
19
  componentId: "sc-1gmh4sk-3"
@@ -20,7 +21,7 @@ const BelowLabel = /* @__PURE__ */ styled.div.withConfig({
20
21
  const LabelSwitchWrapper = /* @__PURE__ */ styled.div.withConfig({
21
22
  displayName: "Switchstyles__LabelSwitchWrapper",
22
23
  componentId: "sc-1gmh4sk-4"
23
- })(["display:flex;flex-direction:row;justify-content:flex-start;align-items:center;"]);
24
+ })(["display:flex;flex-direction:row;justify-content:flex-start;align-items:center;", ":hover:not(:disabled) + .switch-texts .switch-label{color:", ";}", ":disabled + .switch-texts .switch-label{color:", ";opacity:0.4;}"], Toggle, (props) => props.theme.palette["grey-800"], Toggle, (props) => props.theme.palette["grey-600"]);
24
25
  const Error = /* @__PURE__ */ styled.div.withConfig({
25
26
  displayName: "Switchstyles__Error",
26
27
  componentId: "sc-1gmh4sk-5"
@@ -1,15 +1,32 @@
1
- import { SwitchProps as AntdSwitchProps } from 'antd';
2
- import { ReactNode } from 'react';
1
+ import { ButtonHTMLAttributes, CSSProperties, MouseEvent, ReactNode } from 'react';
3
2
  import { TooltipProps as DsTooltipProps } from '@synerise/ds-tooltip';
4
- type TooltipProps = {
5
- tooltipIcon?: ReactNode;
6
- tooltip?: ReactNode;
7
- tooltipConfig?: DsTooltipProps;
3
+ import { DataAttributes } from '@synerise/ds-utils';
4
+ export type SwitchSize = 'small' | 'default';
5
+ export type SwitchChangeHandler = (checked: boolean, event: MouseEvent<HTMLButtonElement>) => void;
6
+ /** antd-Switch-style controls (kept back-compatible). */
7
+ type SwitchControlProps = {
8
+ checked?: boolean;
9
+ defaultChecked?: boolean;
10
+ loading?: boolean;
11
+ /** Accepted for API compatibility — the DS switch renders at a single fixed size. */
12
+ size?: SwitchSize;
13
+ onChange?: SwitchChangeHandler;
14
+ onClick?: SwitchChangeHandler;
8
15
  };
9
- export type Props = Omit<AntdSwitchProps, 'size'> & {
10
- errorText?: ReactNode;
16
+ /**
17
+ * Bare DS toggle (the `RawSwitch` export). A `<button role="switch">` that also forwards native
18
+ * button attributes (name, onBlur/onFocus, etc.) + `data-*` so React-Final-Form `{...input}` spreads
19
+ * keep working. `disabled`, `id`, `className`, `style`, `title`, `tabIndex` come from the native attrs.
20
+ */
21
+ export type RawSwitchProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'onClick' | 'type' | 'value'> & SwitchControlProps & DataAttributes;
22
+ export type Props = RawSwitchProps & {
11
23
  label: ReactNode;
12
24
  description?: ReactNode;
25
+ errorText?: ReactNode;
13
26
  withFormElementMargin?: boolean;
14
- } & TooltipProps;
27
+ tooltipIcon?: ReactNode;
28
+ tooltip?: ReactNode;
29
+ tooltipConfig?: DsTooltipProps;
30
+ style?: CSSProperties;
31
+ };
15
32
  export {};
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { default, RawSwitch } from './Switch';
2
- export type { Props as SwitchProps } from './Switch.types';
2
+ export type { Props as SwitchProps, RawSwitchProps } from './Switch.types';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import { RawSwitch, Switch } from "./Switch.js";
1
+ import { Switch } from "./Switch.js";
2
+ import { default as default2 } from "./RawSwitch.js";
2
3
  export {
3
- RawSwitch,
4
+ default2 as RawSwitch,
4
5
  Switch as default
5
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-switch",
3
- "version": "1.2.32",
3
+ "version": "1.2.33",
4
4
  "description": "Switch UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "synerise/synerise-design",
@@ -41,19 +41,19 @@
41
41
  ],
42
42
  "types": "dist/index.d.ts",
43
43
  "dependencies": {
44
- "@synerise/ds-form-field": "^1.3.22",
45
- "@synerise/ds-typography": "^1.1.25",
44
+ "@synerise/ds-form-field": "^1.3.23",
45
+ "@synerise/ds-typography": "^1.1.26",
46
+ "@synerise/ds-utils": "^1.10.1",
46
47
  "classnames": "^2.5.1"
47
48
  },
48
49
  "devDependencies": {
49
- "@synerise/ds-tooltip": "^1.5.2"
50
+ "@synerise/ds-tooltip": "^1.5.3"
50
51
  },
51
52
  "peerDependencies": {
52
53
  "@synerise/ds-core": "*",
53
- "antd": "4.24.16",
54
54
  "react": ">=16.9.0 <= 18.3.1",
55
55
  "styled-components": "^5.3.3",
56
56
  "vitest": "4"
57
57
  },
58
- "gitHead": "fe3379f50afdce6d8c61a2222ebbf03324107c95"
58
+ "gitHead": "d8c64070f58f14e3fb1bfbcbf00d1e3b8fd51eb8"
59
59
  }
File without changes
@@ -1 +0,0 @@
1
- .ant-switch{margin:0;padding:0;color:#6a7580;font-size:13px;font-variant:tabular-nums;line-height:1.38;list-style:none;font-feature-settings:'tnum';position:relative;display:inline-block;box-sizing:border-box;min-width:44px;height:22px;line-height:22px;vertical-align:middle;background-color:#b5bdc3;border:0;border-radius:100px;cursor:pointer;transition:all .2s;user-select:none}.ant-switch:focus{outline:0;box-shadow:0 0 0 2px rgba(181,189,195,.1)}.ant-switch-checked:focus{box-shadow:0 0 0 2px #e6f4ff}.ant-switch:focus:hover{box-shadow:none}.ant-switch-checked{background-color:#54cb0b}.ant-switch-disabled,.ant-switch-loading{cursor:not-allowed;opacity:.4}.ant-switch-disabled *,.ant-switch-loading *{box-shadow:none;cursor:not-allowed}.ant-switch-inner{display:block;margin:0 7px 0 25px;color:#fff;font-size:11px;transition:margin .2s}.ant-switch-checked .ant-switch-inner{margin:0 25px 0 7px}.ant-switch-handle{position:absolute;top:2px;left:2px;width:18px;height:18px;transition:all .2s ease-in-out}.ant-switch-handle::before{position:absolute;top:0;right:0;bottom:0;left:0;background-color:#fff;border-radius:9px;box-shadow:0 2px 4px 0 rgba(0,35,11,.2);transition:all .2s ease-in-out;content:''}.ant-switch-checked .ant-switch-handle{left:calc(100% - 18px - 2px)}.ant-switch:not(.ant-switch-disabled):active .ant-switch-handle::before{right:-30%;left:0}.ant-switch:not(.ant-switch-disabled):active.ant-switch-checked .ant-switch-handle::before{right:0;left:-30%}.ant-switch-loading-icon.anticon{position:relative;top:2.5px;color:rgba(0,0,0,.65);vertical-align:top}.ant-switch-checked .ant-switch-loading-icon{color:#54cb0b}.ant-switch-small{min-width:28px;height:16px;line-height:16px}.ant-switch-small .ant-switch-inner{margin:0 5px 0 18px;font-size:11px}.ant-switch-small .ant-switch-handle{width:12px;height:12px}.ant-switch-small .ant-switch-loading-icon{top:1.5px;font-size:9px}.ant-switch-small.ant-switch-checked .ant-switch-inner{margin:0 18px 0 5px}.ant-switch-small.ant-switch-checked .ant-switch-handle{left:calc(100% - 12px - 2px)}.ant-switch-rtl{direction:rtl}.ant-switch-rtl .ant-switch-inner{margin:0 25px 0 7px}.ant-switch-rtl .ant-switch-handle{right:2px;left:auto}.ant-switch-rtl:not(.ant-switch-rtl-disabled):active .ant-switch-handle::before{right:0;left:-30%}.ant-switch-rtl:not(.ant-switch-rtl-disabled):active.ant-switch-checked .ant-switch-handle::before{right:-30%;left:0}.ant-switch-rtl.ant-switch-checked .ant-switch-inner{margin:0 7px 0 25px}.ant-switch-rtl.ant-switch-checked .ant-switch-handle{right:calc(100% - 18px - 2px)}.ant-switch-rtl.ant-switch-small.ant-switch-checked .ant-switch-handle{right:calc(100% - 12px - 2px)}.ant-switch{min-width:unset;width:28px;height:16px;border:2px solid transparent}.ant-switch:not(.ant-switch-disabled):active::after,.ant-switch:not(.ant-switch-disabled):active::before{width:12px}.ant-switch+.switch-texts .switch-label{color:#57616d}.ant-switch.ant-switch.error{background-color:#f52922}.ant-switch:hover{background-color:#949ea6}.ant-switch:hover+.switch-texts .switch-label{color:#384350}.ant-switch .ant-switch-handle{width:12px;height:12px;top:0;left:0}.ant-switch .ant-switch-handle::before{box-shadow:none}.ant-switch.ant-switch .ant-click-animating-node{display:none}.ant-switch-checked:hover{background-color:#76dc25}.ant-switch-checked+.switch-texts .switch-label{color:#57616d}.ant-switch-checked+.switch-texts .switch-label:hover{color:#384350}.ant-switch-checked.ant-switch-checked .ant-switch-handle{left:calc(100% - 12px)}.ant-switch:focus{box-shadow:none;border:2px solid #0b68ff}.ant-switch-checked::after{margin-left:0}.ant-switch:not(.ant-switch-checked)::after{left:0}.ant-switch-disabled+.switch-texts .switch-label{color:#6a7580;opacity:.4}.ant-switch-disabled+.switch-texts .switch-description{color:#6a7580;opacity:.4}