@edux-design/chips 0.0.1

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/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # @edux-design/chips
2
+
3
+ Token-driven filter chips that compose existing primitives (like `TagNumber`) without extra props. Each chip renders a pill with a count, label, and optional dismiss control that mirrors the spec in `chips.png`.
4
+
5
+ ---
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm add @edux-design/chips @edux-design/utils @edux-design/icons
11
+ # or
12
+ npm install @edux-design/chips @edux-design/utils @edux-design/icons
13
+ ```
14
+
15
+ The package ships React components and depends on `react@^19.1.0` / `react-dom@^19.1.0`.
16
+
17
+ ---
18
+
19
+ ## Usage
20
+
21
+ ```jsx
22
+ import { Chip } from "@edux-design/chips";
23
+ import { TagNumber } from "@edux-design/tags";
24
+
25
+ export function Filters({ onRemove }) {
26
+ return (
27
+ <Chip label="Label" onRemove={onRemove}>
28
+ <TagNumber variant="brand" tone="solid">999</TagNumber>
29
+ </Chip>
30
+ );
31
+ }
32
+ ```
33
+
34
+ ### Key Props
35
+
36
+ | Prop | Description |
37
+ | ---- | ----------- |
38
+ | `label` | Primary text rendered inside the chip (truncated when needed). |
39
+ | `size` | `"default"` (40px tall) or `"small"` (32px tall). |
40
+ | `onRemove` | When provided, renders a close icon button that calls the handler. |
41
+ | `removeLabel` | Accessible label for the close button. Defaults to `"Remove chip"`. |
42
+ | `disabled` | Mutes colors, disables the close button, and removes pointer interactions. |
43
+
44
+ `children` are rendered before the label, so you can compose `TagNumber` (or any other primitive) directly inside the chip without a dedicated prop.
45
+
46
+ ---
47
+
48
+ ## Development
49
+
50
+ ```bash
51
+ pnpm --filter @edux-design/chips lint
52
+ pnpm --filter @edux-design/chips check-types
53
+ pnpm --filter @edux-design/chips build
54
+ ```
55
+
56
+ Stories live under `src/demos/Chip.stories.jsx` with size + state examples pulled from `chips.png`.
57
+
58
+ ---
59
+
60
+ ## Notes
61
+
62
+ - Focus, hover, pressed, dragged, and inactive visuals are all handled via Tailwind utility classes wired to the shared design tokens.
63
+ - The chip container uses `focus-within` so the focus ring appears when the remove button is tabbed to.
64
+ - Feel free to slot other components ahead of the label; the layout simply spaces whatever you supply, so TagNumber composition stays entirely declarative.
@@ -0,0 +1,16 @@
1
+ import * as react from 'react';
2
+
3
+ /**
4
+ * Token-driven chip that composes existing primitives (i.e. TagNumber) inside.
5
+ *
6
+ * @typedef {React.HTMLAttributes<HTMLDivElement> & {
7
+ * label?: React.ReactNode,
8
+ * size?: "default"|"small",
9
+ * onRemove?: (event: React.MouseEvent<HTMLButtonElement>) => void,
10
+ * removeLabel?: string,
11
+ * disabled?: boolean,
12
+ * }} ChipProps
13
+ */
14
+ declare const Chip: react.ForwardRefExoticComponent<react.RefAttributes<any>>;
15
+
16
+ export { Chip };
@@ -0,0 +1,16 @@
1
+ import * as react from 'react';
2
+
3
+ /**
4
+ * Token-driven chip that composes existing primitives (i.e. TagNumber) inside.
5
+ *
6
+ * @typedef {React.HTMLAttributes<HTMLDivElement> & {
7
+ * label?: React.ReactNode,
8
+ * size?: "default"|"small",
9
+ * onRemove?: (event: React.MouseEvent<HTMLButtonElement>) => void,
10
+ * removeLabel?: string,
11
+ * disabled?: boolean,
12
+ * }} ChipProps
13
+ */
14
+ declare const Chip: react.ForwardRefExoticComponent<react.RefAttributes<any>>;
15
+
16
+ export { Chip };
package/dist/index.js ADDED
@@ -0,0 +1,125 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/index.js
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ Chip: () => Chip
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/elements/Chip.jsx
37
+ var import_react = __toESM(require("react"));
38
+ var import_utils = require("@edux-design/utils");
39
+ var import_icons = require("@edux-design/icons");
40
+ var import_jsx_runtime = require("react/jsx-runtime");
41
+ var SIZE_MAP = {
42
+ default: {
43
+ container: "text-sm min-h-[40px] px-8 py-6 gap-8",
44
+ close: "h-[16px] w-[16px]"
45
+ },
46
+ small: {
47
+ container: "text-xs min-h-[32px] px-8 py-4 gap-6",
48
+ close: "h-[16px] w-[16px]"
49
+ }
50
+ };
51
+ var BASE_STYLES = (0, import_utils.cx)(
52
+ "inline-flex items-center rounded-full border border-border-minimal bg-bg-base text-fg-base w-fit",
53
+ "transition-all duration-200 ease-out",
54
+ "hover:border-border-primary-base hover:bg-bg-primary-subtle",
55
+ "active:border-border-primary-emphasis active:bg-bg-primary-subtle-90",
56
+ "focus-within:shadow-focus focus-within:border-border-emphasis",
57
+ "shadow-sm"
58
+ );
59
+ var DISABLED_STYLES = "bg-bg-inactive text-fg-inactive border-border-subtle cursor-not-allowed pointer-events-none";
60
+ var Chip = (0, import_react.forwardRef)(function Chip2({
61
+ label,
62
+ children,
63
+ size = "default",
64
+ onRemove,
65
+ removeLabel = "Remove chip",
66
+ disabled = false,
67
+ className,
68
+ ...rest
69
+ }, ref) {
70
+ const sizeStyles = SIZE_MAP[size] ?? SIZE_MAP.default;
71
+ const containerClass = (0, import_utils.cx)(
72
+ BASE_STYLES,
73
+ sizeStyles.container,
74
+ disabled && DISABLED_STYLES,
75
+ className
76
+ );
77
+ const shouldRenderLabel = label !== void 0 && label !== null && label !== false;
78
+ const shouldRenderChildren = children !== void 0 && children !== null && !(Array.isArray(children) && children.length === 0);
79
+ const normalizedChildren = import_react.default.Children.toArray(children).filter(
80
+ (child) => child !== null && child !== void 0 && child !== false
81
+ );
82
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
83
+ "div",
84
+ {
85
+ ref,
86
+ className: containerClass,
87
+ "data-disabled": disabled ? "true" : void 0,
88
+ ...rest,
89
+ children: [
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex min-w-0 flex-1 items-center gap-6", children: [
91
+ shouldRenderChildren && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex items-center gap-4 shrink-0 [&>*]:shrink-0", children: normalizedChildren.map(
92
+ (child, index) => (0, import_react.isValidElement)(child) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex items-center", children: child }, child.key ?? index) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: child }, index)
93
+ ) }),
94
+ shouldRenderLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate text-left", children: label })
95
+ ] }),
96
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
97
+ "button",
98
+ {
99
+ type: "button",
100
+ disabled,
101
+ "aria-label": removeLabel,
102
+ onClick: (event) => {
103
+ event.stopPropagation();
104
+ onRemove(event);
105
+ },
106
+ className: (0, import_utils.cx)(
107
+ "ml-4 inline-flex items-center justify-center rounded-full text-fg-subtle",
108
+ "transition-colors duration-150 ease-in-out",
109
+ "hover:bg-bg-primary-subtle hover:text-fg-primary-base",
110
+ "focus-visible:shadow-focus focus-visible:outline-none",
111
+ "active:bg-bg-primary-subtle-90",
112
+ disabled && "opacity-60 pointer-events-none bg-transparent text-fg-inactive",
113
+ sizeStyles.close
114
+ ),
115
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.Close, {})
116
+ }
117
+ )
118
+ ]
119
+ }
120
+ );
121
+ });
122
+ // Annotate the CommonJS export names for ESM import in node:
123
+ 0 && (module.exports = {
124
+ Chip
125
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,89 @@
1
+ // src/elements/Chip.jsx
2
+ import React, { forwardRef, isValidElement } from "react";
3
+ import { cx } from "@edux-design/utils";
4
+ import { Close } from "@edux-design/icons";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ var SIZE_MAP = {
7
+ default: {
8
+ container: "text-sm min-h-[40px] px-8 py-6 gap-8",
9
+ close: "h-[16px] w-[16px]"
10
+ },
11
+ small: {
12
+ container: "text-xs min-h-[32px] px-8 py-4 gap-6",
13
+ close: "h-[16px] w-[16px]"
14
+ }
15
+ };
16
+ var BASE_STYLES = cx(
17
+ "inline-flex items-center rounded-full border border-border-minimal bg-bg-base text-fg-base w-fit",
18
+ "transition-all duration-200 ease-out",
19
+ "hover:border-border-primary-base hover:bg-bg-primary-subtle",
20
+ "active:border-border-primary-emphasis active:bg-bg-primary-subtle-90",
21
+ "focus-within:shadow-focus focus-within:border-border-emphasis",
22
+ "shadow-sm"
23
+ );
24
+ var DISABLED_STYLES = "bg-bg-inactive text-fg-inactive border-border-subtle cursor-not-allowed pointer-events-none";
25
+ var Chip = forwardRef(function Chip2({
26
+ label,
27
+ children,
28
+ size = "default",
29
+ onRemove,
30
+ removeLabel = "Remove chip",
31
+ disabled = false,
32
+ className,
33
+ ...rest
34
+ }, ref) {
35
+ const sizeStyles = SIZE_MAP[size] ?? SIZE_MAP.default;
36
+ const containerClass = cx(
37
+ BASE_STYLES,
38
+ sizeStyles.container,
39
+ disabled && DISABLED_STYLES,
40
+ className
41
+ );
42
+ const shouldRenderLabel = label !== void 0 && label !== null && label !== false;
43
+ const shouldRenderChildren = children !== void 0 && children !== null && !(Array.isArray(children) && children.length === 0);
44
+ const normalizedChildren = React.Children.toArray(children).filter(
45
+ (child) => child !== null && child !== void 0 && child !== false
46
+ );
47
+ return /* @__PURE__ */ jsxs(
48
+ "div",
49
+ {
50
+ ref,
51
+ className: containerClass,
52
+ "data-disabled": disabled ? "true" : void 0,
53
+ ...rest,
54
+ children: [
55
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-6", children: [
56
+ shouldRenderChildren && /* @__PURE__ */ jsx("span", { className: "flex items-center gap-4 shrink-0 [&>*]:shrink-0", children: normalizedChildren.map(
57
+ (child, index) => isValidElement(child) ? /* @__PURE__ */ jsx("span", { className: "flex items-center", children: child }, child.key ?? index) : /* @__PURE__ */ jsx("span", { children: child }, index)
58
+ ) }),
59
+ shouldRenderLabel && /* @__PURE__ */ jsx("span", { className: "truncate text-left", children: label })
60
+ ] }),
61
+ onRemove && /* @__PURE__ */ jsx(
62
+ "button",
63
+ {
64
+ type: "button",
65
+ disabled,
66
+ "aria-label": removeLabel,
67
+ onClick: (event) => {
68
+ event.stopPropagation();
69
+ onRemove(event);
70
+ },
71
+ className: cx(
72
+ "ml-4 inline-flex items-center justify-center rounded-full text-fg-subtle",
73
+ "transition-colors duration-150 ease-in-out",
74
+ "hover:bg-bg-primary-subtle hover:text-fg-primary-base",
75
+ "focus-visible:shadow-focus focus-visible:outline-none",
76
+ "active:bg-bg-primary-subtle-90",
77
+ disabled && "opacity-60 pointer-events-none bg-transparent text-fg-inactive",
78
+ sizeStyles.close
79
+ ),
80
+ children: /* @__PURE__ */ jsx(Close, {})
81
+ }
82
+ )
83
+ ]
84
+ }
85
+ );
86
+ });
87
+ export {
88
+ Chip
89
+ };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@edux-design/chips",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "sideEffects": [
6
+ "**/*.css"
7
+ ],
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.js",
16
+ "types": "./dist/index.d.ts"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "lint": "eslint . --max-warnings 0",
21
+ "build": "tsup src/index.js --format esm,cjs --dts",
22
+ "dev": "tsup src/index.js --watch --format esm,cjs --dts",
23
+ "generate:component": "turbo gen react-component",
24
+ "check-types": "tsc --noEmit"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.9.2",
28
+ "tailwindcss": "^4.1.12",
29
+ "postcss": "^8.5.6",
30
+ "tsup": "^8.5.0",
31
+ "@tailwindcss/cli": "^4.1.12",
32
+ "@tailwindcss/postcss": "^4.1.12"
33
+ },
34
+ "dependencies": {
35
+ "@edux-design/utils": "*",
36
+ "@edux-design/icons": "*",
37
+ "react": "^19.1.0",
38
+ "react-dom": "^19.1.0"
39
+ },
40
+ "peerDependencies": {
41
+ "react": "^19.1.0",
42
+ "react-dom": "^19.1.0"
43
+ }
44
+ }