@inshorts/glint-ui 0.3.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.
- package/README.md +60 -0
- package/package.json +56 -0
- package/src/alert.tsx +74 -0
- package/src/autocomplete.tsx +666 -0
- package/src/badge.tsx +60 -0
- package/src/breadcrumb.tsx +71 -0
- package/src/button.tsx +113 -0
- package/src/card.tsx +79 -0
- package/src/checkbox.tsx +42 -0
- package/src/clipboard.ts +144 -0
- package/src/collapsible.tsx +63 -0
- package/src/confirm-dialog.tsx +66 -0
- package/src/copy-button.tsx +58 -0
- package/src/data-table.tsx +190 -0
- package/src/date-range-picker/dateRange.ts +142 -0
- package/src/date-range-picker/index.tsx +366 -0
- package/src/dialogLayer.ts +142 -0
- package/src/feature-access-gate.tsx +38 -0
- package/src/field.tsx +39 -0
- package/src/image-uploader.tsx +181 -0
- package/src/index.ts +35 -0
- package/src/input.tsx +16 -0
- package/src/label.tsx +23 -0
- package/src/modal.tsx +110 -0
- package/src/page-header.tsx +75 -0
- package/src/pagination.tsx +116 -0
- package/src/segmented-control.tsx +155 -0
- package/src/select.tsx +105 -0
- package/src/separator.tsx +32 -0
- package/src/side-drawer.tsx +87 -0
- package/src/spinner.tsx +38 -0
- package/src/spreadsheet-grid.tsx +264 -0
- package/src/state-panel.tsx +46 -0
- package/src/switch.tsx +46 -0
- package/src/table.tsx +110 -0
- package/src/tabs.tsx +118 -0
- package/src/textarea.tsx +32 -0
- package/src/utils.ts +6 -0
- package/theme.css +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @inshorts/glint-ui
|
|
2
|
+
|
|
3
|
+
Shared Tailwind 4 UI kit for Inshorts Next panels — the same components that
|
|
4
|
+
ship in `inpix-panel` (`src/lib/ui/`), extracted so every panel can reuse them.
|
|
5
|
+
|
|
6
|
+
Includes Button, Input, Label, Card, Table, Modal, Select, DataTable,
|
|
7
|
+
DateRangePicker, Tabs, ImageUploader (upload handlers injected), and the panel
|
|
8
|
+
theme tokens.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
Until this is published to the private registry, link the local checkout that
|
|
13
|
+
sits next to your panel repos:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# from inshorts-sales-panel-next (or inpix-panel, users-crm, …)
|
|
17
|
+
pnpm add @inshorts/glint-ui@file:../inshorts-npm-modules/glint/ui
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
After publish:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add @inshorts/glint-ui
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Peer deps: `react` and `react-dom` ^19.3.
|
|
27
|
+
|
|
28
|
+
## Wire it into a Next + Tailwind 4 panel
|
|
29
|
+
|
|
30
|
+
1. Depend on the package (see above).
|
|
31
|
+
2. Add `transpilePackages: ["@inshorts/glint-ui"]` in `next.config.mjs`.
|
|
32
|
+
3. In `src/styles/globals.css`:
|
|
33
|
+
|
|
34
|
+
```css
|
|
35
|
+
@import "tailwindcss";
|
|
36
|
+
@plugin "tailwindcss-animate";
|
|
37
|
+
@import "@inshorts/glint-ui/theme.css";
|
|
38
|
+
|
|
39
|
+
/* So Tailwind emits classes used only inside the package. */
|
|
40
|
+
@source "../../node_modules/@inshorts/glint-ui/src";
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
4. Import components:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { Button, Modal, cn } from "@inshorts/glint-ui";
|
|
47
|
+
// or a single file:
|
|
48
|
+
import { Button } from "@inshorts/glint-ui/button";
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`ImageUploader` takes `uploadFile` / `uploadFromUrl` props — each panel passes
|
|
52
|
+
its own BFF upload route. Absolute `https://` pastes work without a handler.
|
|
53
|
+
|
|
54
|
+
## Develop
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd glint/ui
|
|
58
|
+
npm install
|
|
59
|
+
npm run typecheck
|
|
60
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@inshorts/glint-ui",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Glint Tailwind 4 UI kit for Inshorts Next panels.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": [
|
|
8
|
+
"**/*.css"
|
|
9
|
+
],
|
|
10
|
+
"main": "./src/index.ts",
|
|
11
|
+
"types": "./src/index.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./src/index.ts",
|
|
14
|
+
"./theme.css": "./theme.css",
|
|
15
|
+
"./utils": "./src/utils.ts",
|
|
16
|
+
"./clipboard": "./src/clipboard.ts",
|
|
17
|
+
"./dialogLayer": "./src/dialogLayer.ts",
|
|
18
|
+
"./date-range-picker": "./src/date-range-picker/index.tsx",
|
|
19
|
+
"./date-range-picker/dateRange": "./src/date-range-picker/dateRange.ts",
|
|
20
|
+
"./*": "./src/*.tsx",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"src",
|
|
25
|
+
"theme.css",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/NewsInShorts/inshorts-npm-modules.git",
|
|
34
|
+
"directory": "glint/ui"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": "^19.3.0",
|
|
38
|
+
"react-dom": "^19.3.0"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@radix-ui/react-slot": "^1.3.3",
|
|
42
|
+
"class-variance-authority": "^0.7.1",
|
|
43
|
+
"clsx": "^2.1.1",
|
|
44
|
+
"lucide-react": "^1.49.0",
|
|
45
|
+
"tailwind-merge": "^3.7.0",
|
|
46
|
+
"@inshorts/glint-theme": "0.3.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/react": "^19.3.0",
|
|
50
|
+
"@types/react-dom": "^19.3.0",
|
|
51
|
+
"typescript": "^5.9.3"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"typecheck": "tsc --noEmit"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/alert.tsx
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
import { cn } from "./utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The inline message banner — a failed load, a warning above a form, a note.
|
|
8
|
+
*
|
|
9
|
+
* This was the most duplicated markup in the panel: thirty blocks across
|
|
10
|
+
* twenty-eight files, spelled seven different ways. `px-3 py-2` in most places
|
|
11
|
+
* and `px-4 py-3` in others, `text-rose-700` here and `text-destructive`
|
|
12
|
+
* there — all meaning "something went wrong".
|
|
13
|
+
*
|
|
14
|
+
* `role` is derived from the variant rather than left to callers. An error a
|
|
15
|
+
* user needs to act on should interrupt a screen reader; a note should not.
|
|
16
|
+
* Almost none of the hand-rolled copies set either.
|
|
17
|
+
*/
|
|
18
|
+
const alertVariants = cva("rounded-lg border px-3 py-2 text-sm", {
|
|
19
|
+
variants: {
|
|
20
|
+
variant: {
|
|
21
|
+
danger: "border-rose-200 bg-rose-50 text-rose-700",
|
|
22
|
+
warning: "border-amber-200 bg-amber-50 text-amber-800",
|
|
23
|
+
success: "border-emerald-200 bg-emerald-50 text-emerald-800",
|
|
24
|
+
info: "border-sky-200 bg-sky-50 text-sky-800",
|
|
25
|
+
/**
|
|
26
|
+
* The quiet state of a banner that also has loud ones — "no default
|
|
27
|
+
* campaign set" next to "this is the default". Without it those callers
|
|
28
|
+
* keep a ternary of raw class strings and the shared component only
|
|
29
|
+
* covers half of what they draw.
|
|
30
|
+
*/
|
|
31
|
+
neutral: "border-border bg-muted/40 text-muted-foreground",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
// Failure is what a banner almost always reports here, and defaulting to
|
|
36
|
+
// it means the noisy case cannot be forgotten.
|
|
37
|
+
variant: "danger",
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export interface AlertProps
|
|
42
|
+
extends
|
|
43
|
+
React.HTMLAttributes<HTMLDivElement>,
|
|
44
|
+
VariantProps<typeof alertVariants> {
|
|
45
|
+
/**
|
|
46
|
+
* A control belonging to the message, such as Retry. Given one, the banner
|
|
47
|
+
* lays out as a row and keeps the action at its end.
|
|
48
|
+
*/
|
|
49
|
+
action?: React.ReactNode;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
|
53
|
+
({ className, variant, action, children, ...props }, ref) => (
|
|
54
|
+
<div
|
|
55
|
+
ref={ref}
|
|
56
|
+
role={variant === "danger" || variant == null ? "alert" : "status"}
|
|
57
|
+
className={cn(
|
|
58
|
+
alertVariants({ variant }),
|
|
59
|
+
action && "flex flex-wrap items-center justify-between gap-3",
|
|
60
|
+
className,
|
|
61
|
+
)}
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
{/* Wrapped so the action sits opposite the text rather than being
|
|
65
|
+
pushed around by whatever the caller passed as children. */}
|
|
66
|
+
{action ? <span>{children}</span> : children}
|
|
67
|
+
{action}
|
|
68
|
+
</div>
|
|
69
|
+
),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
Alert.displayName = "Alert";
|
|
73
|
+
|
|
74
|
+
export { alertVariants };
|