@djangocfg/ui-core 2.1.428 → 2.1.429

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/ui-core",
3
- "version": "2.1.428",
3
+ "version": "2.1.429",
4
4
  "description": "Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps",
5
5
  "keywords": [
6
6
  "ui-components",
@@ -106,7 +106,7 @@
106
106
  "check": "tsc --noEmit"
107
107
  },
108
108
  "peerDependencies": {
109
- "@djangocfg/i18n": "^2.1.428",
109
+ "@djangocfg/i18n": "^2.1.429",
110
110
  "consola": "^3.4.2",
111
111
  "lucide-react": "^0.545.0",
112
112
  "moment": "^2.30.1",
@@ -180,8 +180,8 @@
180
180
  "@chenglou/pretext": "*"
181
181
  },
182
182
  "devDependencies": {
183
- "@djangocfg/i18n": "^2.1.428",
184
- "@djangocfg/typescript-config": "^2.1.428",
183
+ "@djangocfg/i18n": "^2.1.429",
184
+ "@djangocfg/typescript-config": "^2.1.429",
185
185
  "@types/node": "^25.2.3",
186
186
  "@types/react": "^19.2.15",
187
187
  "@types/react-dom": "^19.2.3",
@@ -119,6 +119,14 @@ Button.displayName = "Button"
119
119
  * cmd-click, and the Next.js adapter (if mounted) all work out of the box.
120
120
  * Drop-in replacement for the previous native-`<a>` version.
121
121
  */
122
+ /**
123
+ * ButtonLink — anchor styled as a Button.
124
+ *
125
+ * **Disabled / loading.** An `<a>` has no native `disabled`, so we emulate it
126
+ * the shadcn-recommended way: `aria-disabled` + `tabIndex={-1}` +
127
+ * `pointer-events-none opacity-50`, and we cancel the click. `loading` adds the
128
+ * same inert state plus a spinner — keeping parity with `<Button>`.
129
+ */
122
130
  export interface ButtonLinkProps
123
131
  extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>,
124
132
  VariantProps<typeof buttonVariants> {
@@ -129,21 +137,46 @@ export interface ButtonLinkProps
129
137
  scroll?: boolean
130
138
  /** Hint for the host framework's prefetcher (Next.js). */
131
139
  prefetch?: boolean | null
140
+ /** Inert + dimmed; click is cancelled and it's removed from tab order. */
141
+ disabled?: boolean
142
+ /** Inert + dimmed + spinner (e.g. while an action resolves). */
143
+ loading?: boolean
132
144
  }
133
145
 
134
146
  const ButtonLink = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
135
- ({ className, variant, size, elevated, href, replace, scroll, prefetch, children, ...props }, ref) => {
147
+ (
148
+ { className, variant, size, elevated, href, replace, scroll, prefetch, disabled = false, loading = false, onClick, children, ...props },
149
+ ref,
150
+ ) => {
151
+ // `<a>` can't be natively disabled — emulate it (aria + tab-order + no
152
+ // pointer events) and hard-cancel the click so navigation can't fire.
153
+ const inert = disabled || loading
154
+ const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
155
+ if (inert) {
156
+ e.preventDefault()
157
+ return
158
+ }
159
+ onClick?.(e)
160
+ }
161
+
136
162
  return (
137
163
  <Link
138
164
  href={href}
139
165
  replace={replace}
140
166
  scroll={scroll}
141
167
  prefetch={prefetch}
142
- className={cn(buttonVariants({ variant, size, elevated, className }))}
168
+ className={cn(
169
+ buttonVariants({ variant, size, elevated, className }),
170
+ inert && 'pointer-events-none opacity-50',
171
+ )}
143
172
  ref={ref}
173
+ onClick={handleClick}
174
+ aria-disabled={inert || undefined}
175
+ tabIndex={inert ? -1 : undefined}
144
176
  {...props}
145
177
  >
146
- {children}
178
+ {loading && <Loader2 className="size-4 animate-spin" />}
179
+ {loading ? filterIcons(children) : children}
147
180
  </Link>
148
181
  )
149
182
  }