@inshorts/glint-ui 0.5.1 → 0.5.2

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 CHANGED
@@ -48,8 +48,9 @@ import { Button, Modal, cn } from "@inshorts/glint-ui";
48
48
  import { Button } from "@inshorts/glint-ui/button";
49
49
  ```
50
50
 
51
- `ImageUploader` takes `uploadFile` / `uploadFromUrl` props — each panel passes
52
- its own BFF upload route. Absolute `https://` pastes work without a handler.
51
+ `ImageUploader` keeps Upload and URL paste enabled by default. Pass
52
+ `uploadFile` / `uploadFromUrl` for the panel BFF; without them, paste still
53
+ applies any URL as-is and Upload surfaces a config error if a file is picked.
53
54
 
54
55
  ## Develop
55
56
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inshorts/glint-ui",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Glint Tailwind 4 UI kit for Inshorts Next panels.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -18,12 +18,14 @@ export type ImageUploaderProps = {
18
18
  accept?: string;
19
19
  /**
20
20
  * Upload a picked file and return its hosted URL.
21
- * Required for the Upload button — without it, only URL paste works.
21
+ * Injected by the panel — Upload stays enabled either way; without a
22
+ * handler, picking a file surfaces a configuration error.
22
23
  */
23
24
  uploadFile?: (file: File) => Promise<string>;
24
25
  /**
25
- * Resolve a non-http pasted value (relative path, etc.) into a hosted URL.
26
- * Absolute `http(s)` values are applied as-is without calling this.
26
+ * Optional transform for pasted values (e.g. host a relative path).
27
+ * When omitted, any pasted non-empty string is applied as-is. Absolute
28
+ * `http(s)` URLs never call this.
27
29
  */
28
30
  uploadFromUrl?: (imageUrl: string) => Promise<string>;
29
31
  };
@@ -31,8 +33,9 @@ export type ImageUploaderProps = {
31
33
  /**
32
34
  * Reusable image uploader.
33
35
  *
34
- * Hosting is injected: each panel passes its own `uploadFile` / `uploadFromUrl`
35
- * so the kit stays free of panel-specific API routes.
36
+ * Upload and URL paste are both enabled by default. Hosting is injected:
37
+ * each panel passes `uploadFile` / `uploadFromUrl` so the kit stays free of
38
+ * panel-specific API routes.
36
39
  */
37
40
  export function ImageUploader({
38
41
  value = "",
@@ -48,6 +51,7 @@ export function ImageUploader({
48
51
  const inputRef = React.useRef<HTMLInputElement>(null);
49
52
  const [uploading, setUploading] = React.useState(false);
50
53
  const [error, setError] = React.useState<string | null>(null);
54
+ const busy = Boolean(disabled || uploading);
51
55
 
52
56
  const handleFile = async (file: File) => {
53
57
  if (!uploadFile) {
@@ -74,18 +78,14 @@ export function ImageUploader({
74
78
  }
75
79
  if (trimmed === value) return;
76
80
 
77
- // Already-hosted absolute URLs can be used as-is.
78
- if (/^https?:\/\//i.test(trimmed)) {
81
+ // Absolute URLs — and any paste when no transform is configured — apply
82
+ // as-is. Paste is never gated behind a disabled input.
83
+ if (!uploadFromUrl || /^https?:\/\//i.test(trimmed)) {
79
84
  setError(null);
80
85
  onChange(trimmed);
81
86
  return;
82
87
  }
83
88
 
84
- if (!uploadFromUrl) {
85
- setError("Paste an absolute image URL, or configure URL upload.");
86
- return;
87
- }
88
-
89
89
  setUploading(true);
90
90
  setError(null);
91
91
  try {
@@ -109,7 +109,7 @@ export function ImageUploader({
109
109
  type="file"
110
110
  accept={accept}
111
111
  className="hidden"
112
- disabled={disabled || uploading || !uploadFile}
112
+ disabled={busy}
113
113
  onChange={(e) => {
114
114
  const file = e.target.files?.[0];
115
115
  if (file) void handleFile(file);
@@ -119,7 +119,7 @@ export function ImageUploader({
119
119
  type="button"
120
120
  variant="outline"
121
121
  size="sm"
122
- disabled={disabled || uploading || !uploadFile}
122
+ disabled={busy}
123
123
  onClick={() => inputRef.current?.click()}
124
124
  >
125
125
  {uploading ? (
@@ -134,7 +134,7 @@ export function ImageUploader({
134
134
  type="button"
135
135
  variant="ghost"
136
136
  size="sm"
137
- disabled={disabled || uploading}
137
+ disabled={busy}
138
138
  onClick={() => onChange("")}
139
139
  aria-label="Clear image"
140
140
  >
@@ -148,7 +148,7 @@ export function ImageUploader({
148
148
  <Input
149
149
  key={value || "empty"}
150
150
  defaultValue={value}
151
- disabled={disabled || uploading}
151
+ disabled={busy}
152
152
  placeholder="Or paste image URL…"
153
153
  onBlur={(e) => {
154
154
  void handleUrl(e.target.value);