@lattice-php/lattice 0.1.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/LICENSE.md +21 -0
- package/README.md +39 -0
- package/dist/action/components/action-group.d.ts +10 -0
- package/dist/action/components/action-group.js +79 -0
- package/dist/action/components/action-group.js.map +1 -0
- package/dist/action/components/action.d.ts +26 -0
- package/dist/action/components/action.js +87 -0
- package/dist/action/components/action.js.map +1 -0
- package/dist/action/effects.d.ts +30 -0
- package/dist/action/effects.js +44 -0
- package/dist/action/effects.js.map +1 -0
- package/dist/action/index.d.ts +1 -0
- package/dist/action/index.js +15 -0
- package/dist/action/index.js.map +1 -0
- package/dist/appearance/index.d.ts +9 -0
- package/dist/appearance/index.js +66 -0
- package/dist/appearance/index.js.map +1 -0
- package/dist/clipboard/index.d.ts +5 -0
- package/dist/clipboard/index.js +24 -0
- package/dist/clipboard/index.js.map +1 -0
- package/dist/core/component-ref.d.ts +8 -0
- package/dist/core/component-ref.js +15 -0
- package/dist/core/component-ref.js.map +1 -0
- package/dist/core/components/badge.d.ts +19 -0
- package/dist/core/components/badge.js +32 -0
- package/dist/core/components/badge.js.map +1 -0
- package/dist/core/components/button.d.ts +23 -0
- package/dist/core/components/button.js +68 -0
- package/dist/core/components/button.js.map +1 -0
- package/dist/core/components/card.d.ts +19 -0
- package/dist/core/components/card.js +62 -0
- package/dist/core/components/card.js.map +1 -0
- package/dist/core/components/confirm-dialog.d.ts +13 -0
- package/dist/core/components/confirm-dialog.js +47 -0
- package/dist/core/components/confirm-dialog.js.map +1 -0
- package/dist/core/components/fragment.d.ts +12 -0
- package/dist/core/components/fragment.js +62 -0
- package/dist/core/components/fragment.js.map +1 -0
- package/dist/core/components/grid.d.ts +10 -0
- package/dist/core/components/grid.js +16 -0
- package/dist/core/components/grid.js.map +1 -0
- package/dist/core/components/heading.d.ts +11 -0
- package/dist/core/components/heading.js +39 -0
- package/dist/core/components/heading.js.map +1 -0
- package/dist/core/components/index.d.ts +1 -0
- package/dist/core/components/index.js +36 -0
- package/dist/core/components/index.js.map +1 -0
- package/dist/core/components/link.d.ts +18 -0
- package/dist/core/components/link.js +26 -0
- package/dist/core/components/link.js.map +1 -0
- package/dist/core/components/modal.d.ts +13 -0
- package/dist/core/components/modal.js +75 -0
- package/dist/core/components/modal.js.map +1 -0
- package/dist/core/components/segmented-control.d.ts +16 -0
- package/dist/core/components/segmented-control.js +30 -0
- package/dist/core/components/segmented-control.js.map +1 -0
- package/dist/core/components/segmented-pills.d.ts +13 -0
- package/dist/core/components/segmented-pills.js +31 -0
- package/dist/core/components/segmented-pills.js.map +1 -0
- package/dist/core/components/spinner.d.ts +2 -0
- package/dist/core/components/spinner.js +16 -0
- package/dist/core/components/spinner.js.map +1 -0
- package/dist/core/components/stack.d.ts +13 -0
- package/dist/core/components/stack.js +47 -0
- package/dist/core/components/stack.js.map +1 -0
- package/dist/core/components/tabs.d.ts +22 -0
- package/dist/core/components/tabs.js +118 -0
- package/dist/core/components/tabs.js.map +1 -0
- package/dist/core/components/text.d.ts +11 -0
- package/dist/core/components/text.js +18 -0
- package/dist/core/components/text.js.map +1 -0
- package/dist/core/props.d.ts +14 -0
- package/dist/core/props.js +30 -0
- package/dist/core/props.js.map +1 -0
- package/dist/core/registry.d.ts +26 -0
- package/dist/core/registry.js +36 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/renderer.d.ts +16 -0
- package/dist/core/renderer.js +61 -0
- package/dist/core/renderer.js.map +1 -0
- package/dist/core/types.d.ts +55 -0
- package/dist/core/types.js +0 -0
- package/dist/events/event-bridge.d.ts +14 -0
- package/dist/events/event-bridge.js +75 -0
- package/dist/events/event-bridge.js.map +1 -0
- package/dist/events/event-names.d.ts +21 -0
- package/dist/events/event-names.js +22 -0
- package/dist/events/event-names.js.map +1 -0
- package/dist/form/components/base/checkbox.d.ts +4 -0
- package/dist/form/components/base/checkbox.js +22 -0
- package/dist/form/components/base/checkbox.js.map +1 -0
- package/dist/form/components/base/field.d.ts +9 -0
- package/dist/form/components/base/field.js +38 -0
- package/dist/form/components/base/field.js.map +1 -0
- package/dist/form/components/base/input-error.d.ts +4 -0
- package/dist/form/components/base/input-error.js +14 -0
- package/dist/form/components/base/input-error.js.map +1 -0
- package/dist/form/components/base/input.d.ts +3 -0
- package/dist/form/components/base/input.js +16 -0
- package/dist/form/components/base/input.js.map +1 -0
- package/dist/form/components/base/label.d.ts +4 -0
- package/dist/form/components/base/label.js +16 -0
- package/dist/form/components/base/label.js.map +1 -0
- package/dist/form/components/base/password-input.d.ts +7 -0
- package/dist/form/components/base/password-input.js +29 -0
- package/dist/form/components/base/password-input.js.map +1 -0
- package/dist/form/components/base/submit-button.d.ts +6 -0
- package/dist/form/components/base/submit-button.js +46 -0
- package/dist/form/components/base/submit-button.js.map +1 -0
- package/dist/form/components/base/textarea.d.ts +3 -0
- package/dist/form/components/base/textarea.js +15 -0
- package/dist/form/components/base/textarea.js.map +1 -0
- package/dist/form/components/conditions.d.ts +25 -0
- package/dist/form/components/conditions.js +62 -0
- package/dist/form/components/conditions.js.map +1 -0
- package/dist/form/components/context.d.ts +20 -0
- package/dist/form/components/context.js +30 -0
- package/dist/form/components/context.js.map +1 -0
- package/dist/form/components/fields/checkbox.d.ts +16 -0
- package/dist/form/components/fields/checkbox.js +51 -0
- package/dist/form/components/fields/checkbox.js.map +1 -0
- package/dist/form/components/fields/choice.d.ts +14 -0
- package/dist/form/components/fields/choice.js +49 -0
- package/dist/form/components/fields/choice.js.map +1 -0
- package/dist/form/components/fields/date-input.d.ts +20 -0
- package/dist/form/components/fields/date-input.js +33 -0
- package/dist/form/components/fields/date-input.js.map +1 -0
- package/dist/form/components/fields/hidden-input.d.ts +10 -0
- package/dist/form/components/fields/hidden-input.js +12 -0
- package/dist/form/components/fields/hidden-input.js.map +1 -0
- package/dist/form/components/fields/number-input.d.ts +23 -0
- package/dist/form/components/fields/number-input.js +55 -0
- package/dist/form/components/fields/number-input.js.map +1 -0
- package/dist/form/components/fields/password-input.d.ts +29 -0
- package/dist/form/components/fields/password-input.js +73 -0
- package/dist/form/components/fields/password-input.js.map +1 -0
- package/dist/form/components/fields/rich-editor.d.ts +17 -0
- package/dist/form/components/fields/rich-editor.js +302 -0
- package/dist/form/components/fields/rich-editor.js.map +1 -0
- package/dist/form/components/fields/select.d.ts +23 -0
- package/dist/form/components/fields/select.js +182 -0
- package/dist/form/components/fields/select.js.map +1 -0
- package/dist/form/components/fields/submit-button.d.ts +10 -0
- package/dist/form/components/fields/submit-button.js +14 -0
- package/dist/form/components/fields/submit-button.js.map +1 -0
- package/dist/form/components/fields/text-input.d.ts +21 -0
- package/dist/form/components/fields/text-input.js +33 -0
- package/dist/form/components/fields/text-input.js.map +1 -0
- package/dist/form/components/fields/textarea.d.ts +20 -0
- package/dist/form/components/fields/textarea.js +32 -0
- package/dist/form/components/fields/textarea.js.map +1 -0
- package/dist/form/components/form-transport.d.ts +8 -0
- package/dist/form/components/form-transport.js +31 -0
- package/dist/form/components/form-transport.js.map +1 -0
- package/dist/form/components/form.d.ts +21 -0
- package/dist/form/components/form.js +126 -0
- package/dist/form/components/form.js.map +1 -0
- package/dist/form/components/index.d.ts +11 -0
- package/dist/form/components/index.js +12 -0
- package/dist/form/components/resolved-nodes.d.ts +6 -0
- package/dist/form/components/resolved-nodes.js +20 -0
- package/dist/form/components/resolved-nodes.js.map +1 -0
- package/dist/form/components/types.d.ts +7 -0
- package/dist/form/components/types.js +0 -0
- package/dist/form/components/use-controlled-field.d.ts +16 -0
- package/dist/form/components/use-controlled-field.js +33 -0
- package/dist/form/components/use-controlled-field.js.map +1 -0
- package/dist/form/components/use-dependent-field.d.ts +3 -0
- package/dist/form/components/use-dependent-field.js +18 -0
- package/dist/form/components/use-dependent-field.js.map +1 -0
- package/dist/form/components/use-field-commit.d.ts +14 -0
- package/dist/form/components/use-field-commit.js +30 -0
- package/dist/form/components/use-field-commit.js.map +1 -0
- package/dist/form/components/use-form-resolver.d.ts +2 -0
- package/dist/form/components/use-form-resolver.js +57 -0
- package/dist/form/components/use-form-resolver.js.map +1 -0
- package/dist/form/components/values.d.ts +7 -0
- package/dist/form/components/values.js +37 -0
- package/dist/form/components/values.js.map +1 -0
- package/dist/form/index.d.ts +1 -0
- package/dist/form/index.js +33 -0
- package/dist/form/index.js.map +1 -0
- package/dist/form/skeleton.d.ts +2 -0
- package/dist/form/skeleton.js +21 -0
- package/dist/form/skeleton.js.map +1 -0
- package/dist/generated/types.d.ts +17 -0
- package/dist/generated/types.js +0 -0
- package/dist/icons/default-icons.d.ts +3 -0
- package/dist/icons/default-icons.js +44 -0
- package/dist/icons/default-icons.js.map +1 -0
- package/dist/icons/dynamic-lucide-renderer.d.ts +2 -0
- package/dist/icons/dynamic-lucide-renderer.js +18 -0
- package/dist/icons/dynamic-lucide-renderer.js.map +1 -0
- package/dist/icons/icon-renderer.d.ts +14 -0
- package/dist/icons/icon-renderer.js +35 -0
- package/dist/icons/icon-renderer.js.map +1 -0
- package/dist/icons/index.d.ts +2 -0
- package/dist/icons/index.js +2 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +14 -0
- package/dist/inertia.d.ts +17 -0
- package/dist/inertia.js +26 -0
- package/dist/inertia.js.map +1 -0
- package/dist/lattice.css +247 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.js +13 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/menu/index.d.ts +1 -0
- package/dist/menu/index.js +2 -0
- package/dist/menu/use-menu.d.ts +2 -0
- package/dist/menu/use-menu.js +9 -0
- package/dist/menu/use-menu.js.map +1 -0
- package/dist/page.d.ts +6 -0
- package/dist/page.js +30 -0
- package/dist/page.js.map +1 -0
- package/dist/provider.d.ts +7 -0
- package/dist/provider.js +19 -0
- package/dist/provider.js.map +1 -0
- package/dist/registry.d.ts +1 -0
- package/dist/registry.js +11 -0
- package/dist/registry.js.map +1 -0
- package/dist/table/bulk.d.ts +18 -0
- package/dist/table/bulk.js +44 -0
- package/dist/table/bulk.js.map +1 -0
- package/dist/table/components/bulk-bar.d.ts +11 -0
- package/dist/table/components/bulk-bar.js +76 -0
- package/dist/table/components/bulk-bar.js.map +1 -0
- package/dist/table/components/column-filter-control.d.ts +14 -0
- package/dist/table/components/column-filter-control.js +244 -0
- package/dist/table/components/column-filter-control.js.map +1 -0
- package/dist/table/components/column-header.d.ts +7 -0
- package/dist/table/components/column-header.js +37 -0
- package/dist/table/components/column-header.js.map +1 -0
- package/dist/table/components/filter-stack-bar.d.ts +7 -0
- package/dist/table/components/filter-stack-bar.js +35 -0
- package/dist/table/components/filter-stack-bar.js.map +1 -0
- package/dist/table/components/filter-value-input.d.ts +11 -0
- package/dist/table/components/filter-value-input.js +82 -0
- package/dist/table/components/filter-value-input.js.map +1 -0
- package/dist/table/components/pagination.d.ts +14 -0
- package/dist/table/components/pagination.js +67 -0
- package/dist/table/components/pagination.js.map +1 -0
- package/dist/table/components/sort-bar.d.ts +7 -0
- package/dist/table/components/sort-bar.js +43 -0
- package/dist/table/components/sort-bar.js.map +1 -0
- package/dist/table/components/table-action-node.d.ts +4 -0
- package/dist/table/components/table-action-node.js +24 -0
- package/dist/table/components/table-action-node.js.map +1 -0
- package/dist/table/components/table-cell.d.ts +5 -0
- package/dist/table/components/table-cell.js +63 -0
- package/dist/table/components/table-cell.js.map +1 -0
- package/dist/table/components/table.d.ts +3 -0
- package/dist/table/components/table.js +189 -0
- package/dist/table/components/table.js.map +1 -0
- package/dist/table/format.d.ts +3 -0
- package/dist/table/format.js +41 -0
- package/dist/table/format.js.map +1 -0
- package/dist/table/index.d.ts +1 -0
- package/dist/table/index.js +10 -0
- package/dist/table/index.js.map +1 -0
- package/dist/table/payload.d.ts +9 -0
- package/dist/table/payload.js +46 -0
- package/dist/table/payload.js.map +1 -0
- package/dist/table/query.d.ts +12 -0
- package/dist/table/query.js +83 -0
- package/dist/table/query.js.map +1 -0
- package/dist/table/types.d.ts +67 -0
- package/dist/table/types.js +0 -0
- package/dist/table/use-table-selection.d.ts +12 -0
- package/dist/table/use-table-selection.js +46 -0
- package/dist/table/use-table-selection.js.map +1 -0
- package/dist/table/use-table.d.ts +19 -0
- package/dist/table/use-table.js +157 -0
- package/dist/table/use-table.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +0 -0
- package/package.json +151 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) Manuel Christlieb <manuel@christlieb.eu>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/logo-dark.svg">
|
|
4
|
+
<img alt="Lattice" src="docs/assets/logo.svg" width="320">
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://packagist.org/packages/lattice-php/lattice"><img alt="Latest version on Packagist" src="https://img.shields.io/packagist/v/lattice-php/lattice.svg?style=flat-square"></a>
|
|
10
|
+
<a href="https://www.npmjs.com/package/@lattice-php/lattice"><img alt="Latest version on npm" src="https://img.shields.io/npm/v/@lattice-php/lattice.svg?style=flat-square"></a>
|
|
11
|
+
<a href="https://github.com/lattice-php/lattice/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/lattice-php/lattice/ci.yml?branch=main&label=CI&style=flat-square"></a>
|
|
12
|
+
<a href="https://packagist.org/packages/lattice-php/lattice"><img alt="Total downloads" src="https://img.shields.io/packagist/dt/lattice-php/lattice.svg?style=flat-square"></a>
|
|
13
|
+
<a href="https://packagist.org/packages/lattice-php/lattice"><img alt="License" src="https://img.shields.io/packagist/l/lattice-php/lattice.svg?style=flat-square"></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<strong>Server-driven React components for Laravel and Inertia.</strong>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
Lattice lets you describe your interface — pages, forms, tables, actions, and menus — in PHP on the server and render it with real React components on the client over Inertia. You keep building the way you already do in Laravel, while your users get a polished React front end, with no hand-wired API and no UI contract duplicated across two languages.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
composer require lattice-php/lattice
|
|
28
|
+
npm install @lattice-php/lattice
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
See [Installation](https://latticephp.com/getting-started/installation/) and [Frontend Setup](https://latticephp.com/getting-started/frontend-setup/) for the full setup.
|
|
32
|
+
|
|
33
|
+
## Documentation
|
|
34
|
+
|
|
35
|
+
Full documentation, guides, and examples live at **[latticephp.com](https://latticephp.com)**.
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
The MIT License (MIT). See [LICENSE.md](LICENSE.md) for details.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RendererComponent } from '../../../../core/types';
|
|
2
|
+
declare module '../../../../core/types' {
|
|
3
|
+
interface ComponentProps {
|
|
4
|
+
"action.group": {
|
|
5
|
+
label?: string;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
declare const ActionGroupComponent: RendererComponent<"action.group">;
|
|
10
|
+
export default ActionGroupComponent;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { getStringProp } from "../../core/props.js";
|
|
2
|
+
import { Button } from "../../core/components/button.js";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { MoreHorizontal } from "lucide-react";
|
|
6
|
+
import { createPortal } from "react-dom";
|
|
7
|
+
//#region resources/js/action/components/action-group.tsx
|
|
8
|
+
var ActionGroupComponent = ({ children, node }) => {
|
|
9
|
+
const label = getStringProp(node.props, "label", "Actions");
|
|
10
|
+
const [open, setOpen] = useState(false);
|
|
11
|
+
const [position, setPosition] = useState(null);
|
|
12
|
+
const buttonRef = useRef(null);
|
|
13
|
+
const menuRef = useRef(null);
|
|
14
|
+
const updatePosition = useCallback(() => {
|
|
15
|
+
const rect = buttonRef.current?.getBoundingClientRect();
|
|
16
|
+
if (!rect) return;
|
|
17
|
+
setPosition({
|
|
18
|
+
right: Math.max(8, window.innerWidth - rect.right),
|
|
19
|
+
top: rect.bottom + 8
|
|
20
|
+
});
|
|
21
|
+
}, []);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!open) return;
|
|
24
|
+
updatePosition();
|
|
25
|
+
const closeWhenOutside = (event) => {
|
|
26
|
+
const target = event.target;
|
|
27
|
+
if (target instanceof Node && (buttonRef.current?.contains(target) || menuRef.current?.contains(target))) return;
|
|
28
|
+
setOpen(false);
|
|
29
|
+
};
|
|
30
|
+
const closeOnEscape = (event) => {
|
|
31
|
+
if (event.key === "Escape") setOpen(false);
|
|
32
|
+
};
|
|
33
|
+
window.addEventListener("resize", updatePosition);
|
|
34
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
35
|
+
document.addEventListener("mousedown", closeWhenOutside);
|
|
36
|
+
document.addEventListener("keydown", closeOnEscape);
|
|
37
|
+
return () => {
|
|
38
|
+
window.removeEventListener("resize", updatePosition);
|
|
39
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
40
|
+
document.removeEventListener("mousedown", closeWhenOutside);
|
|
41
|
+
document.removeEventListener("keydown", closeOnEscape);
|
|
42
|
+
};
|
|
43
|
+
}, [open, updatePosition]);
|
|
44
|
+
const toggle = () => {
|
|
45
|
+
updatePosition();
|
|
46
|
+
setOpen((current) => !current);
|
|
47
|
+
};
|
|
48
|
+
const menu = open && position && typeof document !== "undefined" ? createPortal(/* @__PURE__ */ jsx("div", {
|
|
49
|
+
ref: menuRef,
|
|
50
|
+
"aria-label": label,
|
|
51
|
+
className: "fixed z-50 grid min-w-40 gap-1 rounded-lt-sm border border-lt-border bg-lt-popover p-1 text-lt-popover-fg shadow-md [&>button]:w-full [&>button]:justify-start",
|
|
52
|
+
role: "menu",
|
|
53
|
+
style: position,
|
|
54
|
+
children
|
|
55
|
+
}), document.body) : null;
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
57
|
+
className: "inline-flex",
|
|
58
|
+
"data-lattice-component": node.id,
|
|
59
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
60
|
+
ref: buttonRef,
|
|
61
|
+
"aria-label": label,
|
|
62
|
+
"aria-expanded": open,
|
|
63
|
+
"aria-haspopup": "menu",
|
|
64
|
+
className: "size-8 text-lt-muted-fg shadow-none hover:text-lt-fg",
|
|
65
|
+
onClick: toggle,
|
|
66
|
+
size: "icon",
|
|
67
|
+
type: "button",
|
|
68
|
+
variant: "ghost",
|
|
69
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, {
|
|
70
|
+
"aria-hidden": "true",
|
|
71
|
+
className: "size-4"
|
|
72
|
+
})
|
|
73
|
+
}), menu]
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
77
|
+
export { ActionGroupComponent as default };
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=action-group.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-group.js","names":[],"sources":["../../../resources/js/action/components/action-group.tsx"],"sourcesContent":["import { MoreHorizontal } from \"lucide-react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Button } from \"@lattice/lattice/core/components/button\";\nimport { getStringProp } from \"@lattice/lattice/core/props\";\nimport type { RendererComponent } from \"@lattice/lattice/core/types\";\n\ndeclare module \"@lattice/lattice/core/types\" {\n interface ComponentProps {\n \"action.group\": {\n label?: string;\n };\n }\n}\n\nconst ActionGroupComponent: RendererComponent<\"action.group\"> = ({ children, node }) => {\n const label = getStringProp(node.props, \"label\", \"Actions\");\n const [open, setOpen] = useState(false);\n const [position, setPosition] = useState<{ right: number; top: number } | null>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const updatePosition = useCallback(() => {\n const rect = buttonRef.current?.getBoundingClientRect();\n\n if (!rect) {\n return;\n }\n\n setPosition({\n right: Math.max(8, window.innerWidth - rect.right),\n top: rect.bottom + 8,\n });\n }, []);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n updatePosition();\n\n const closeWhenOutside = (event: MouseEvent): void => {\n const target = event.target;\n\n if (\n target instanceof Node &&\n (buttonRef.current?.contains(target) || menuRef.current?.contains(target))\n ) {\n return;\n }\n\n setOpen(false);\n };\n\n const closeOnEscape = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n setOpen(false);\n }\n };\n\n window.addEventListener(\"resize\", updatePosition);\n window.addEventListener(\"scroll\", updatePosition, true);\n document.addEventListener(\"mousedown\", closeWhenOutside);\n document.addEventListener(\"keydown\", closeOnEscape);\n\n return () => {\n window.removeEventListener(\"resize\", updatePosition);\n window.removeEventListener(\"scroll\", updatePosition, true);\n document.removeEventListener(\"mousedown\", closeWhenOutside);\n document.removeEventListener(\"keydown\", closeOnEscape);\n };\n }, [open, updatePosition]);\n\n const toggle = (): void => {\n updatePosition();\n setOpen((current) => !current);\n };\n\n const menu =\n open && position && typeof document !== \"undefined\"\n ? createPortal(\n <div\n ref={menuRef}\n aria-label={label}\n className=\"fixed z-50 grid min-w-40 gap-1 rounded-lt-sm border border-lt-border bg-lt-popover p-1 text-lt-popover-fg shadow-md [&>button]:w-full [&>button]:justify-start\"\n role=\"menu\"\n style={position}\n >\n {children}\n </div>,\n document.body,\n )\n : null;\n\n return (\n <div className=\"inline-flex\" data-lattice-component={node.id}>\n <Button\n ref={buttonRef}\n aria-label={label}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n className=\"size-8 text-lt-muted-fg shadow-none hover:text-lt-fg\"\n onClick={toggle}\n size=\"icon\"\n type=\"button\"\n variant=\"ghost\"\n >\n <MoreHorizontal aria-hidden=\"true\" className=\"size-4\" />\n </Button>\n\n {menu}\n </div>\n );\n};\n\nexport default ActionGroupComponent;\n"],"mappings":";;;;;;;AAeA,IAAM,wBAA2D,EAAE,UAAU,WAAW;CACtF,MAAM,QAAQ,cAAc,KAAK,OAAO,SAAS,SAAS;CAC1D,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,CAAC,UAAU,eAAe,SAAgD,IAAI;CACpF,MAAM,YAAY,OAA0B,IAAI;CAChD,MAAM,UAAU,OAAuB,IAAI;CAE3C,MAAM,iBAAiB,kBAAkB;EACvC,MAAM,OAAO,UAAU,SAAS,sBAAsB;EAEtD,IAAI,CAAC,MACH;EAGF,YAAY;GACV,OAAO,KAAK,IAAI,GAAG,OAAO,aAAa,KAAK,KAAK;GACjD,KAAK,KAAK,SAAS;EACrB,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,gBAAgB;EACd,IAAI,CAAC,MACH;EAGF,eAAe;EAEf,MAAM,oBAAoB,UAA4B;GACpD,MAAM,SAAS,MAAM;GAErB,IACE,kBAAkB,SACjB,UAAU,SAAS,SAAS,MAAM,KAAK,QAAQ,SAAS,SAAS,MAAM,IAExE;GAGF,QAAQ,KAAK;EACf;EAEA,MAAM,iBAAiB,UAA+B;GACpD,IAAI,MAAM,QAAQ,UAChB,QAAQ,KAAK;EAEjB;EAEA,OAAO,iBAAiB,UAAU,cAAc;EAChD,OAAO,iBAAiB,UAAU,gBAAgB,IAAI;EACtD,SAAS,iBAAiB,aAAa,gBAAgB;EACvD,SAAS,iBAAiB,WAAW,aAAa;EAElD,aAAa;GACX,OAAO,oBAAoB,UAAU,cAAc;GACnD,OAAO,oBAAoB,UAAU,gBAAgB,IAAI;GACzD,SAAS,oBAAoB,aAAa,gBAAgB;GAC1D,SAAS,oBAAoB,WAAW,aAAa;EACvD;CACF,GAAG,CAAC,MAAM,cAAc,CAAC;CAEzB,MAAM,eAAqB;EACzB,eAAe;EACf,SAAS,YAAY,CAAC,OAAO;CAC/B;CAEA,MAAM,OACJ,QAAQ,YAAY,OAAO,aAAa,cACpC,aACE,oBAAC,OAAD;EACE,KAAK;EACL,cAAY;EACZ,WAAU;EACV,MAAK;EACL,OAAO;EAEN;CACE,CAAA,GACL,SAAS,IACX,IACA;CAEN,OACE,qBAAC,OAAD;EAAK,WAAU;EAAc,0BAAwB,KAAK;YAA1D,CACE,oBAAC,QAAD;GACE,KAAK;GACL,cAAY;GACZ,iBAAe;GACf,iBAAc;GACd,WAAU;GACV,SAAS;GACT,MAAK;GACL,MAAK;GACL,SAAQ;aAER,oBAAC,gBAAD;IAAgB,eAAY;IAAO,WAAU;GAAU,CAAA;EACjD,CAAA,GAEP,IACE;;AAET"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Method } from '@inertiajs/core';
|
|
2
|
+
import { RendererComponent } from '../../../../core/types';
|
|
3
|
+
import { ActionEffect } from '../effects';
|
|
4
|
+
type ActionVariant = "default" | "destructive" | "ghost" | "link" | "outline" | "secondary";
|
|
5
|
+
type ActionConfirmation = {
|
|
6
|
+
cancelLabel?: string;
|
|
7
|
+
confirmLabel?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
};
|
|
11
|
+
declare module '../../../../core/types' {
|
|
12
|
+
interface ComponentProps {
|
|
13
|
+
action: {
|
|
14
|
+
confirmation?: ActionConfirmation;
|
|
15
|
+
effects?: ActionEffect[];
|
|
16
|
+
endpoint?: string;
|
|
17
|
+
icon?: string;
|
|
18
|
+
label?: string;
|
|
19
|
+
ref?: string;
|
|
20
|
+
method?: Method;
|
|
21
|
+
variant?: ActionVariant;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
declare const ActionComponent: RendererComponent<"action">;
|
|
26
|
+
export default ActionComponent;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { withRefHeader } from "../../core/component-ref.js";
|
|
2
|
+
import { getStringProp } from "../../core/props.js";
|
|
3
|
+
import { Button } from "../../core/components/button.js";
|
|
4
|
+
import { Spinner } from "../../core/components/spinner.js";
|
|
5
|
+
import { ConfirmDialog } from "../../core/components/confirm-dialog.js";
|
|
6
|
+
import { IconRenderer } from "../../icons/icon-renderer.js";
|
|
7
|
+
import { dispatchActionEffects, dispatchActionError, getActionEffects } from "../effects.js";
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { router, useHttp } from "@inertiajs/react";
|
|
10
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
//#region resources/js/action/components/action.tsx
|
|
12
|
+
var actionMethods = [
|
|
13
|
+
"delete",
|
|
14
|
+
"get",
|
|
15
|
+
"patch",
|
|
16
|
+
"post",
|
|
17
|
+
"put"
|
|
18
|
+
];
|
|
19
|
+
function getActionMethod(props) {
|
|
20
|
+
const method = getStringProp(props, "method", "post");
|
|
21
|
+
return actionMethods.includes(method) ? method : "post";
|
|
22
|
+
}
|
|
23
|
+
function getConfirmation(props) {
|
|
24
|
+
const confirmation = props?.confirmation;
|
|
25
|
+
if (typeof confirmation !== "object" || confirmation === null || Array.isArray(confirmation)) return null;
|
|
26
|
+
return confirmation;
|
|
27
|
+
}
|
|
28
|
+
var ActionComponent = ({ node }) => {
|
|
29
|
+
const endpoint = getStringProp(node.props, "endpoint");
|
|
30
|
+
const icon = getStringProp(node.props, "icon");
|
|
31
|
+
const label = getStringProp(node.props, "label", "Run action");
|
|
32
|
+
const componentRef = getStringProp(node.props, "ref");
|
|
33
|
+
const method = getActionMethod(node.props);
|
|
34
|
+
const http = useHttp({});
|
|
35
|
+
const [isConfirming, setIsConfirming] = useState(false);
|
|
36
|
+
const confirmation = getConfirmation(node.props);
|
|
37
|
+
const submit = async () => {
|
|
38
|
+
if (!endpoint) return;
|
|
39
|
+
try {
|
|
40
|
+
if (method === "get") {
|
|
41
|
+
router.visit(endpoint, { headers: withRefHeader(componentRef) });
|
|
42
|
+
setIsConfirming(false);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const responseEffects = getActionEffects((await http[method](endpoint, { headers: withRefHeader(componentRef) })).effects);
|
|
46
|
+
dispatchActionEffects(responseEffects.length > 0 ? responseEffects : getActionEffects(node.props?.effects));
|
|
47
|
+
setIsConfirming(false);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
dispatchActionError(error);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const requestSubmit = () => {
|
|
53
|
+
if (confirmation) {
|
|
54
|
+
setIsConfirming(true);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
submit();
|
|
58
|
+
};
|
|
59
|
+
const confirmationTitle = confirmation?.title ?? label;
|
|
60
|
+
const confirmationConfirmLabel = confirmation?.confirmLabel ?? label;
|
|
61
|
+
const confirmationCancelLabel = confirmation?.cancelLabel ?? "Cancel";
|
|
62
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Button, {
|
|
63
|
+
"data-lattice-component": node.id,
|
|
64
|
+
disabled: http.processing || !endpoint,
|
|
65
|
+
onClick: requestSubmit,
|
|
66
|
+
type: "button",
|
|
67
|
+
variant: node.props?.variant ?? "default",
|
|
68
|
+
children: [http.processing ? /* @__PURE__ */ jsx(Spinner, {}) : icon && /* @__PURE__ */ jsx(IconRenderer, {
|
|
69
|
+
className: "size-4",
|
|
70
|
+
icon
|
|
71
|
+
}), label]
|
|
72
|
+
}), isConfirming && confirmation && /* @__PURE__ */ jsx(ConfirmDialog, {
|
|
73
|
+
title: confirmationTitle,
|
|
74
|
+
description: confirmation.description,
|
|
75
|
+
confirmLabel: confirmationConfirmLabel,
|
|
76
|
+
cancelLabel: confirmationCancelLabel,
|
|
77
|
+
confirmVariant: node.props?.variant ?? "default",
|
|
78
|
+
processing: http.processing,
|
|
79
|
+
confirmDisabled: !endpoint,
|
|
80
|
+
onConfirm: () => void submit(),
|
|
81
|
+
onCancel: () => setIsConfirming(false)
|
|
82
|
+
})] });
|
|
83
|
+
};
|
|
84
|
+
//#endregion
|
|
85
|
+
export { ActionComponent as default };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.js","names":[],"sources":["../../../resources/js/action/components/action.tsx"],"sourcesContent":["import { router, useHttp } from \"@inertiajs/react\";\nimport type { Method } from \"@inertiajs/core\";\nimport { useState } from \"react\";\nimport { withRefHeader } from \"@lattice/lattice/core/component-ref\";\nimport { Button } from \"@lattice/lattice/core/components/button\";\nimport { ConfirmDialog } from \"@lattice/lattice/core/components/confirm-dialog\";\nimport { Spinner } from \"@lattice/lattice/core/components/spinner\";\nimport { getStringProp } from \"@lattice/lattice/core/props\";\nimport type { NodeProps, RendererComponent } from \"@lattice/lattice/core/types\";\nimport { IconRenderer } from \"@lattice/lattice/icons\";\nimport { dispatchActionEffects, dispatchActionError, getActionEffects } from \"../effects\";\nimport type { ActionEffect } from \"../effects\";\n\ntype ActionVariant = \"default\" | \"destructive\" | \"ghost\" | \"link\" | \"outline\" | \"secondary\";\n\ntype ActionConfirmation = {\n cancelLabel?: string;\n confirmLabel?: string;\n description?: string;\n title?: string;\n};\n\ntype ActionResponse = {\n data?: Record<string, unknown>;\n effects?: ActionEffect[];\n ok?: boolean;\n};\n\ntype ActionData = Record<string, never>;\n\ndeclare module \"@lattice/lattice/core/types\" {\n interface ComponentProps {\n action: {\n confirmation?: ActionConfirmation;\n effects?: ActionEffect[];\n endpoint?: string;\n icon?: string;\n label?: string;\n ref?: string;\n method?: Method;\n variant?: ActionVariant;\n };\n }\n}\n\nconst actionMethods = [\"delete\", \"get\", \"patch\", \"post\", \"put\"] satisfies Method[];\n\nfunction getActionMethod(props: NodeProps | undefined): Method {\n const method = getStringProp(props, \"method\", \"post\");\n\n return actionMethods.includes(method as Method) ? (method as Method) : \"post\";\n}\n\nfunction getConfirmation(props: NodeProps | undefined): ActionConfirmation | null {\n const confirmation = props?.confirmation;\n\n if (typeof confirmation !== \"object\" || confirmation === null || Array.isArray(confirmation)) {\n return null;\n }\n\n return confirmation;\n}\n\nconst ActionComponent: RendererComponent<\"action\"> = ({ node }) => {\n const endpoint = getStringProp(node.props, \"endpoint\");\n const icon = getStringProp(node.props, \"icon\");\n const label = getStringProp(node.props, \"label\", \"Run action\");\n const componentRef = getStringProp(node.props, \"ref\");\n const method = getActionMethod(node.props);\n const http = useHttp<ActionData, ActionResponse>({});\n const [isConfirming, setIsConfirming] = useState(false);\n const confirmation = getConfirmation(node.props);\n\n const submit = async (): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n try {\n if (method === \"get\") {\n router.visit(endpoint, { headers: withRefHeader(componentRef) });\n setIsConfirming(false);\n\n return;\n }\n\n const response = await http[method](endpoint, { headers: withRefHeader(componentRef) });\n const responseEffects = getActionEffects(response.effects);\n\n dispatchActionEffects(\n responseEffects.length > 0 ? responseEffects : getActionEffects(node.props?.effects),\n );\n setIsConfirming(false);\n } catch (error) {\n dispatchActionError(error);\n }\n };\n\n const requestSubmit = (): void => {\n if (confirmation) {\n setIsConfirming(true);\n\n return;\n }\n\n void submit();\n };\n\n const confirmationTitle = confirmation?.title ?? label;\n const confirmationConfirmLabel = confirmation?.confirmLabel ?? label;\n const confirmationCancelLabel = confirmation?.cancelLabel ?? \"Cancel\";\n\n return (\n <>\n <Button\n data-lattice-component={node.id}\n disabled={http.processing || !endpoint}\n onClick={requestSubmit}\n type=\"button\"\n variant={node.props?.variant ?? \"default\"}\n >\n {http.processing ? <Spinner /> : icon && <IconRenderer className=\"size-4\" icon={icon} />}\n {label}\n </Button>\n\n {isConfirming && confirmation && (\n <ConfirmDialog\n title={confirmationTitle}\n description={confirmation.description}\n confirmLabel={confirmationConfirmLabel}\n cancelLabel={confirmationCancelLabel}\n confirmVariant={node.props?.variant ?? \"default\"}\n processing={http.processing}\n confirmDisabled={!endpoint}\n onConfirm={() => void submit()}\n onCancel={() => setIsConfirming(false)}\n />\n )}\n </>\n );\n};\n\nexport default ActionComponent;\n"],"mappings":";;;;;;;;;;;AA6CA,IAAM,gBAAgB;CAAC;CAAU;CAAO;CAAS;CAAQ;AAAK;AAE9D,SAAS,gBAAgB,OAAsC;CAC7D,MAAM,SAAS,cAAc,OAAO,UAAU,MAAM;CAEpD,OAAO,cAAc,SAAS,MAAgB,IAAK,SAAoB;AACzE;AAEA,SAAS,gBAAgB,OAAyD;CAChF,MAAM,eAAe,OAAO;CAE5B,IAAI,OAAO,iBAAiB,YAAY,iBAAiB,QAAQ,MAAM,QAAQ,YAAY,GACzF,OAAO;CAGT,OAAO;AACT;AAEA,IAAM,mBAAgD,EAAE,WAAW;CACjE,MAAM,WAAW,cAAc,KAAK,OAAO,UAAU;CACrD,MAAM,OAAO,cAAc,KAAK,OAAO,MAAM;CAC7C,MAAM,QAAQ,cAAc,KAAK,OAAO,SAAS,YAAY;CAC7D,MAAM,eAAe,cAAc,KAAK,OAAO,KAAK;CACpD,MAAM,SAAS,gBAAgB,KAAK,KAAK;CACzC,MAAM,OAAO,QAAoC,CAAC,CAAC;CACnD,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,eAAe,gBAAgB,KAAK,KAAK;CAE/C,MAAM,SAAS,YAA2B;EACxC,IAAI,CAAC,UACH;EAGF,IAAI;GACF,IAAI,WAAW,OAAO;IACpB,OAAO,MAAM,UAAU,EAAE,SAAS,cAAc,YAAY,EAAE,CAAC;IAC/D,gBAAgB,KAAK;IAErB;GACF;GAGA,MAAM,kBAAkB,kBAAiB,MADlB,KAAK,QAAQ,UAAU,EAAE,SAAS,cAAc,YAAY,EAAE,CAAC,GACpC,OAAO;GAEzD,sBACE,gBAAgB,SAAS,IAAI,kBAAkB,iBAAiB,KAAK,OAAO,OAAO,CACrF;GACA,gBAAgB,KAAK;EACvB,SAAS,OAAO;GACd,oBAAoB,KAAK;EAC3B;CACF;CAEA,MAAM,sBAA4B;EAChC,IAAI,cAAc;GAChB,gBAAgB,IAAI;GAEpB;EACF;EAEA,OAAY;CACd;CAEA,MAAM,oBAAoB,cAAc,SAAS;CACjD,MAAM,2BAA2B,cAAc,gBAAgB;CAC/D,MAAM,0BAA0B,cAAc,eAAe;CAE7D,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,qBAAC,QAAD;EACE,0BAAwB,KAAK;EAC7B,UAAU,KAAK,cAAc,CAAC;EAC9B,SAAS;EACT,MAAK;EACL,SAAS,KAAK,OAAO,WAAW;YALlC,CAOG,KAAK,aAAa,oBAAC,SAAD,CAAU,CAAA,IAAI,QAAQ,oBAAC,cAAD;GAAc,WAAU;GAAe;EAAO,CAAA,GACtF,KACK;KAEP,gBAAgB,gBACf,oBAAC,eAAD;EACE,OAAO;EACP,aAAa,aAAa;EAC1B,cAAc;EACd,aAAa;EACb,gBAAgB,KAAK,OAAO,WAAW;EACvC,YAAY,KAAK;EACjB,iBAAiB,CAAC;EAClB,iBAAiB,KAAK,OAAO;EAC7B,gBAAgB,gBAAgB,KAAK;CACtC,CAAA,CAEH,EAAA,CAAA;AAEN"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ToastVariant } from '../../../generated/types';
|
|
2
|
+
export type ActionEffect = {
|
|
3
|
+
message?: string;
|
|
4
|
+
type: "toast";
|
|
5
|
+
variant?: ToastVariant;
|
|
6
|
+
} | {
|
|
7
|
+
type: "reloadPage";
|
|
8
|
+
} | {
|
|
9
|
+
component?: string;
|
|
10
|
+
type: "reloadComponent";
|
|
11
|
+
} | {
|
|
12
|
+
type: "redirect";
|
|
13
|
+
url?: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "download";
|
|
16
|
+
url?: string;
|
|
17
|
+
} | {
|
|
18
|
+
modal?: string;
|
|
19
|
+
type: "openModal";
|
|
20
|
+
} | {
|
|
21
|
+
modal?: string;
|
|
22
|
+
type: "closeModal";
|
|
23
|
+
} | {
|
|
24
|
+
form?: string;
|
|
25
|
+
type: "resetForm";
|
|
26
|
+
};
|
|
27
|
+
export declare function dispatchActionEffects(effects: ActionEffect[]): void;
|
|
28
|
+
export declare function dispatchActionError(error: unknown): void;
|
|
29
|
+
export declare function getActionEffects(effects: unknown): ActionEffect[];
|
|
30
|
+
export declare function isActionEffect(effect: unknown): effect is ActionEffect;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { LATTICE_EVENT } from "../events/event-names.js";
|
|
2
|
+
import { router } from "@inertiajs/react";
|
|
3
|
+
//#region resources/js/action/effects.ts
|
|
4
|
+
var eventNames = {
|
|
5
|
+
toast: LATTICE_EVENT.toast,
|
|
6
|
+
reloadComponent: LATTICE_EVENT.reloadComponent,
|
|
7
|
+
reloadPage: LATTICE_EVENT.reloadPage,
|
|
8
|
+
redirect: LATTICE_EVENT.redirect,
|
|
9
|
+
download: LATTICE_EVENT.download,
|
|
10
|
+
openModal: LATTICE_EVENT.openModal,
|
|
11
|
+
closeModal: LATTICE_EVENT.closeModal,
|
|
12
|
+
resetForm: LATTICE_EVENT.resetForm
|
|
13
|
+
};
|
|
14
|
+
function triggerDownload(url) {
|
|
15
|
+
const link = document.createElement("a");
|
|
16
|
+
link.href = url;
|
|
17
|
+
link.rel = "noopener";
|
|
18
|
+
document.body.appendChild(link);
|
|
19
|
+
link.click();
|
|
20
|
+
link.remove();
|
|
21
|
+
}
|
|
22
|
+
function dispatchActionEffects(effects) {
|
|
23
|
+
if (typeof window === "undefined") return;
|
|
24
|
+
for (const effect of effects) {
|
|
25
|
+
if (effect.type === "reloadPage") router.reload();
|
|
26
|
+
if (effect.type === "redirect" && typeof effect.url === "string") router.visit(effect.url);
|
|
27
|
+
if (effect.type === "download" && typeof effect.url === "string") triggerDownload(effect.url);
|
|
28
|
+
window.dispatchEvent(new CustomEvent(eventNames[effect.type], { detail: effect }));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function dispatchActionError(error) {
|
|
32
|
+
if (typeof window === "undefined") return;
|
|
33
|
+
window.dispatchEvent(new CustomEvent(LATTICE_EVENT.actionError, { detail: { error } }));
|
|
34
|
+
}
|
|
35
|
+
function getActionEffects(effects) {
|
|
36
|
+
return Array.isArray(effects) ? effects.filter(isActionEffect) : [];
|
|
37
|
+
}
|
|
38
|
+
function isActionEffect(effect) {
|
|
39
|
+
return typeof effect === "object" && effect !== null && "type" in effect && typeof effect.type === "string" && Object.hasOwn(eventNames, effect.type);
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { dispatchActionEffects, dispatchActionError, getActionEffects, isActionEffect };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=effects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effects.js","names":[],"sources":["../../resources/js/action/effects.ts"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport type { EffectType, ToastVariant } from \"@lattice/lattice/generated/types\";\nimport { LATTICE_EVENT } from \"@lattice/lattice/events/event-names\";\n\nexport type ActionEffect =\n | {\n message?: string;\n type: \"toast\";\n variant?: ToastVariant;\n }\n | {\n type: \"reloadPage\";\n }\n | {\n component?: string;\n type: \"reloadComponent\";\n }\n | {\n type: \"redirect\";\n url?: string;\n }\n | {\n type: \"download\";\n url?: string;\n }\n | {\n modal?: string;\n type: \"openModal\";\n }\n | {\n modal?: string;\n type: \"closeModal\";\n }\n | {\n form?: string;\n type: \"resetForm\";\n };\n\nconst eventNames = {\n toast: LATTICE_EVENT.toast,\n reloadComponent: LATTICE_EVENT.reloadComponent,\n reloadPage: LATTICE_EVENT.reloadPage,\n redirect: LATTICE_EVENT.redirect,\n download: LATTICE_EVENT.download,\n openModal: LATTICE_EVENT.openModal,\n closeModal: LATTICE_EVENT.closeModal,\n resetForm: LATTICE_EVENT.resetForm,\n} satisfies Record<EffectType, string>;\n\nfunction triggerDownload(url: string): void {\n const link = document.createElement(\"a\");\n link.href = url;\n link.rel = \"noopener\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n}\n\nexport function dispatchActionEffects(effects: ActionEffect[]): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n for (const effect of effects) {\n if (effect.type === \"reloadPage\") {\n router.reload();\n }\n\n if (effect.type === \"redirect\" && typeof effect.url === \"string\") {\n router.visit(effect.url);\n }\n\n if (effect.type === \"download\" && typeof effect.url === \"string\") {\n triggerDownload(effect.url);\n }\n\n window.dispatchEvent(new CustomEvent(eventNames[effect.type], { detail: effect }));\n }\n}\n\nexport function dispatchActionError(error: unknown): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.actionError, { detail: { error } }));\n}\n\nexport function getActionEffects(effects: unknown): ActionEffect[] {\n return Array.isArray(effects) ? effects.filter(isActionEffect) : [];\n}\n\nexport function isActionEffect(effect: unknown): effect is ActionEffect {\n return (\n typeof effect === \"object\" &&\n effect !== null &&\n \"type\" in effect &&\n typeof effect.type === \"string\" &&\n Object.hasOwn(eventNames, effect.type)\n );\n}\n"],"mappings":";;;AAsCA,IAAM,aAAa;CACjB,OAAO,cAAc;CACrB,iBAAiB,cAAc;CAC/B,YAAY,cAAc;CAC1B,UAAU,cAAc;CACxB,UAAU,cAAc;CACxB,WAAW,cAAc;CACzB,YAAY,cAAc;CAC1B,WAAW,cAAc;AAC3B;AAEA,SAAS,gBAAgB,KAAmB;CAC1C,MAAM,OAAO,SAAS,cAAc,GAAG;CACvC,KAAK,OAAO;CACZ,KAAK,MAAM;CACX,SAAS,KAAK,YAAY,IAAI;CAC9B,KAAK,MAAM;CACX,KAAK,OAAO;AACd;AAEA,SAAgB,sBAAsB,SAA+B;CACnE,IAAI,OAAO,WAAW,aACpB;CAGF,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,OAAO,SAAS,cAClB,OAAO,OAAO;EAGhB,IAAI,OAAO,SAAS,cAAc,OAAO,OAAO,QAAQ,UACtD,OAAO,MAAM,OAAO,GAAG;EAGzB,IAAI,OAAO,SAAS,cAAc,OAAO,OAAO,QAAQ,UACtD,gBAAgB,OAAO,GAAG;EAG5B,OAAO,cAAc,IAAI,YAAY,WAAW,OAAO,OAAO,EAAE,QAAQ,OAAO,CAAC,CAAC;CACnF;AACF;AAEA,SAAgB,oBAAoB,OAAsB;CACxD,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AACxF;AAEA,SAAgB,iBAAiB,SAAkC;CACjE,OAAO,MAAM,QAAQ,OAAO,IAAI,QAAQ,OAAO,cAAc,IAAI,CAAC;AACpE;AAEA,SAAgB,eAAe,QAAyC;CACtE,OACE,OAAO,WAAW,YAClB,WAAW,QACX,UAAU,UACV,OAAO,OAAO,SAAS,YACvB,OAAO,OAAO,YAAY,OAAO,IAAI;AAEzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const actionComponents: import('../../../core/registry').Plugin;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createPlugin, eagerComponent } from "../core/registry.js";
|
|
2
|
+
import ActionComponent from "./components/action.js";
|
|
3
|
+
import ActionGroupComponent from "./components/action-group.js";
|
|
4
|
+
//#region resources/js/action/index.ts
|
|
5
|
+
var actionComponents = createPlugin({
|
|
6
|
+
components: {
|
|
7
|
+
action: eagerComponent(ActionComponent),
|
|
8
|
+
"action.group": eagerComponent(ActionGroupComponent)
|
|
9
|
+
},
|
|
10
|
+
name: "lattice/action"
|
|
11
|
+
});
|
|
12
|
+
//#endregion
|
|
13
|
+
export { actionComponents };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../resources/js/action/index.ts"],"sourcesContent":["import { createPlugin, eagerComponent } from \"@lattice/lattice/core/registry\";\nimport ActionComponent from \"./components/action\";\nimport ActionGroupComponent from \"./components/action-group\";\n\nexport const actionComponents = createPlugin({\n components: {\n action: eagerComponent(ActionComponent),\n \"action.group\": eagerComponent(ActionGroupComponent),\n },\n name: \"lattice/action\",\n});\n"],"mappings":";;;;AAIA,IAAa,mBAAmB,aAAa;CAC3C,YAAY;EACV,QAAQ,eAAe,eAAe;EACtC,gBAAgB,eAAe,oBAAoB;CACrD;CACA,MAAM;AACR,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Appearance } from '../events/event-bridge';
|
|
2
|
+
export type ResolvedAppearance = "light" | "dark";
|
|
3
|
+
export type UseAppearanceReturn = {
|
|
4
|
+
readonly appearance: Appearance;
|
|
5
|
+
readonly resolvedAppearance: ResolvedAppearance;
|
|
6
|
+
readonly updateAppearance: (mode: Appearance) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function initializeTheme(): void;
|
|
9
|
+
export declare function useAppearance(): UseAppearanceReturn;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
//#region resources/js/appearance/index.ts
|
|
3
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
4
|
+
var currentAppearance = "system";
|
|
5
|
+
var prefersDark = () => {
|
|
6
|
+
if (typeof window === "undefined") return false;
|
|
7
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
8
|
+
};
|
|
9
|
+
var setCookie = (name, value, days = 365) => {
|
|
10
|
+
if (typeof document === "undefined") return;
|
|
11
|
+
const maxAge = days * 24 * 60 * 60;
|
|
12
|
+
document.cookie = `${name}=${value};path=/;max-age=${maxAge};SameSite=Lax`;
|
|
13
|
+
};
|
|
14
|
+
var getStoredAppearance = () => {
|
|
15
|
+
if (typeof window === "undefined") return "system";
|
|
16
|
+
return localStorage.getItem("appearance") || "system";
|
|
17
|
+
};
|
|
18
|
+
var isDarkMode = (appearance) => {
|
|
19
|
+
return appearance === "dark" || appearance === "system" && prefersDark();
|
|
20
|
+
};
|
|
21
|
+
var applyTheme = (appearance) => {
|
|
22
|
+
if (typeof document === "undefined") return;
|
|
23
|
+
const isDark = isDarkMode(appearance);
|
|
24
|
+
document.documentElement.classList.toggle("dark", isDark);
|
|
25
|
+
document.documentElement.style.colorScheme = isDark ? "dark" : "light";
|
|
26
|
+
};
|
|
27
|
+
var subscribe = (callback) => {
|
|
28
|
+
listeners.add(callback);
|
|
29
|
+
return () => listeners.delete(callback);
|
|
30
|
+
};
|
|
31
|
+
var notify = () => listeners.forEach((listener) => listener());
|
|
32
|
+
var mediaQuery = () => {
|
|
33
|
+
if (typeof window === "undefined") return null;
|
|
34
|
+
return window.matchMedia("(prefers-color-scheme: dark)");
|
|
35
|
+
};
|
|
36
|
+
var handleSystemThemeChange = () => applyTheme(currentAppearance);
|
|
37
|
+
function initializeTheme() {
|
|
38
|
+
if (typeof window === "undefined") return;
|
|
39
|
+
if (!localStorage.getItem("appearance")) {
|
|
40
|
+
localStorage.setItem("appearance", "system");
|
|
41
|
+
setCookie("appearance", "system");
|
|
42
|
+
}
|
|
43
|
+
currentAppearance = getStoredAppearance();
|
|
44
|
+
applyTheme(currentAppearance);
|
|
45
|
+
mediaQuery()?.addEventListener("change", handleSystemThemeChange);
|
|
46
|
+
}
|
|
47
|
+
function useAppearance() {
|
|
48
|
+
const appearance = useSyncExternalStore(subscribe, () => currentAppearance, () => "system");
|
|
49
|
+
const resolvedAppearance = isDarkMode(appearance) ? "dark" : "light";
|
|
50
|
+
const updateAppearance = (mode) => {
|
|
51
|
+
currentAppearance = mode;
|
|
52
|
+
localStorage.setItem("appearance", mode);
|
|
53
|
+
setCookie("appearance", mode);
|
|
54
|
+
applyTheme(mode);
|
|
55
|
+
notify();
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
appearance,
|
|
59
|
+
resolvedAppearance,
|
|
60
|
+
updateAppearance
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { initializeTheme, useAppearance };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../resources/js/appearance/index.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport type { Appearance } from \"../events/event-bridge\";\n\nexport type ResolvedAppearance = \"light\" | \"dark\";\n\nexport type UseAppearanceReturn = {\n readonly appearance: Appearance;\n readonly resolvedAppearance: ResolvedAppearance;\n readonly updateAppearance: (mode: Appearance) => void;\n};\n\nconst listeners = new Set<() => void>();\nlet currentAppearance: Appearance = \"system\";\n\nconst prefersDark = (): boolean => {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n};\n\nconst setCookie = (name: string, value: string, days = 365): void => {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const maxAge = days * 24 * 60 * 60;\n document.cookie = `${name}=${value};path=/;max-age=${maxAge};SameSite=Lax`;\n};\n\nconst getStoredAppearance = (): Appearance => {\n if (typeof window === \"undefined\") {\n return \"system\";\n }\n\n return (localStorage.getItem(\"appearance\") as Appearance) || \"system\";\n};\n\nconst isDarkMode = (appearance: Appearance): boolean => {\n return appearance === \"dark\" || (appearance === \"system\" && prefersDark());\n};\n\nconst applyTheme = (appearance: Appearance): void => {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const isDark = isDarkMode(appearance);\n\n document.documentElement.classList.toggle(\"dark\", isDark);\n document.documentElement.style.colorScheme = isDark ? \"dark\" : \"light\";\n};\n\nconst subscribe = (callback: () => void) => {\n listeners.add(callback);\n\n return () => listeners.delete(callback);\n};\n\nconst notify = (): void => listeners.forEach((listener) => listener());\n\nconst mediaQuery = (): MediaQueryList | null => {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n return window.matchMedia(\"(prefers-color-scheme: dark)\");\n};\n\nconst handleSystemThemeChange = (): void => applyTheme(currentAppearance);\n\nexport function initializeTheme(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n if (!localStorage.getItem(\"appearance\")) {\n localStorage.setItem(\"appearance\", \"system\");\n setCookie(\"appearance\", \"system\");\n }\n\n currentAppearance = getStoredAppearance();\n applyTheme(currentAppearance);\n\n mediaQuery()?.addEventListener(\"change\", handleSystemThemeChange);\n}\n\nexport function useAppearance(): UseAppearanceReturn {\n const appearance: Appearance = useSyncExternalStore(\n subscribe,\n () => currentAppearance,\n () => \"system\",\n );\n\n const resolvedAppearance: ResolvedAppearance = isDarkMode(appearance) ? \"dark\" : \"light\";\n\n const updateAppearance = (mode: Appearance): void => {\n currentAppearance = mode;\n\n localStorage.setItem(\"appearance\", mode);\n\n setCookie(\"appearance\", mode);\n\n applyTheme(mode);\n notify();\n };\n\n return { appearance, resolvedAppearance, updateAppearance } as const;\n}\n"],"mappings":";;AAWA,IAAM,4BAAY,IAAI,IAAgB;AACtC,IAAI,oBAAgC;AAEpC,IAAM,oBAA6B;CACjC,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,OAAO,OAAO,WAAW,8BAA8B,EAAE;AAC3D;AAEA,IAAM,aAAa,MAAc,OAAe,OAAO,QAAc;CACnE,IAAI,OAAO,aAAa,aACtB;CAGF,MAAM,SAAS,OAAO,KAAK,KAAK;CAChC,SAAS,SAAS,GAAG,KAAK,GAAG,MAAM,kBAAkB,OAAO;AAC9D;AAEA,IAAM,4BAAwC;CAC5C,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,OAAQ,aAAa,QAAQ,YAAY,KAAoB;AAC/D;AAEA,IAAM,cAAc,eAAoC;CACtD,OAAO,eAAe,UAAW,eAAe,YAAY,YAAY;AAC1E;AAEA,IAAM,cAAc,eAAiC;CACnD,IAAI,OAAO,aAAa,aACtB;CAGF,MAAM,SAAS,WAAW,UAAU;CAEpC,SAAS,gBAAgB,UAAU,OAAO,QAAQ,MAAM;CACxD,SAAS,gBAAgB,MAAM,cAAc,SAAS,SAAS;AACjE;AAEA,IAAM,aAAa,aAAyB;CAC1C,UAAU,IAAI,QAAQ;CAEtB,aAAa,UAAU,OAAO,QAAQ;AACxC;AAEA,IAAM,eAAqB,UAAU,SAAS,aAAa,SAAS,CAAC;AAErE,IAAM,mBAA0C;CAC9C,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,OAAO,OAAO,WAAW,8BAA8B;AACzD;AAEA,IAAM,gCAAsC,WAAW,iBAAiB;AAExE,SAAgB,kBAAwB;CACtC,IAAI,OAAO,WAAW,aACpB;CAGF,IAAI,CAAC,aAAa,QAAQ,YAAY,GAAG;EACvC,aAAa,QAAQ,cAAc,QAAQ;EAC3C,UAAU,cAAc,QAAQ;CAClC;CAEA,oBAAoB,oBAAoB;CACxC,WAAW,iBAAiB;CAE5B,WAAW,GAAG,iBAAiB,UAAU,uBAAuB;AAClE;AAEA,SAAgB,gBAAqC;CACnD,MAAM,aAAyB,qBAC7B,iBACM,yBACA,QACR;CAEA,MAAM,qBAAyC,WAAW,UAAU,IAAI,SAAS;CAEjF,MAAM,oBAAoB,SAA2B;EACnD,oBAAoB;EAEpB,aAAa,QAAQ,cAAc,IAAI;EAEvC,UAAU,cAAc,IAAI;EAE5B,WAAW,IAAI;EACf,OAAO;CACT;CAEA,OAAO;EAAE;EAAY;EAAoB;CAAiB;AAC5D"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type CopiedValue = string | null;
|
|
2
|
+
export type CopyFn = (text: string) => Promise<boolean>;
|
|
3
|
+
export type UseClipboardReturn = [CopiedValue, CopyFn];
|
|
4
|
+
export declare function copyToClipboard(text: string): Promise<boolean>;
|
|
5
|
+
export declare function useClipboard(): UseClipboardReturn;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
//#region resources/js/clipboard/index.ts
|
|
3
|
+
async function copyToClipboard(text) {
|
|
4
|
+
if (!navigator?.clipboard) return false;
|
|
5
|
+
try {
|
|
6
|
+
await navigator.clipboard.writeText(text);
|
|
7
|
+
return true;
|
|
8
|
+
} catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function useClipboard() {
|
|
13
|
+
const [copiedText, setCopiedText] = useState(null);
|
|
14
|
+
const copy = async (text) => {
|
|
15
|
+
const copied = await copyToClipboard(text);
|
|
16
|
+
setCopiedText(copied ? text : null);
|
|
17
|
+
return copied;
|
|
18
|
+
};
|
|
19
|
+
return [copiedText, copy];
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { copyToClipboard, useClipboard };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../resources/js/clipboard/index.ts"],"sourcesContent":["import { useState } from \"react\";\n\nexport type CopiedValue = string | null;\nexport type CopyFn = (text: string) => Promise<boolean>;\nexport type UseClipboardReturn = [CopiedValue, CopyFn];\n\nexport async function copyToClipboard(text: string): Promise<boolean> {\n if (!navigator?.clipboard) {\n return false;\n }\n\n try {\n await navigator.clipboard.writeText(text);\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport function useClipboard(): UseClipboardReturn {\n const [copiedText, setCopiedText] = useState<CopiedValue>(null);\n\n const copy: CopyFn = async (text) => {\n const copied = await copyToClipboard(text);\n\n setCopiedText(copied ? text : null);\n\n return copied;\n };\n\n return [copiedText, copy];\n}\n"],"mappings":";;AAMA,eAAsB,gBAAgB,MAAgC;CACpE,IAAI,CAAC,WAAW,WACd,OAAO;CAGT,IAAI;EACF,MAAM,UAAU,UAAU,UAAU,IAAI;EAExC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,eAAmC;CACjD,MAAM,CAAC,YAAY,iBAAiB,SAAsB,IAAI;CAE9D,MAAM,OAAe,OAAO,SAAS;EACnC,MAAM,SAAS,MAAM,gBAAgB,IAAI;EAEzC,cAAc,SAAS,OAAO,IAAI;EAElC,OAAO;CACT;CAEA,OAAO,CAAC,YAAY,IAAI;AAC1B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed component reference travels to the server as the `X-Lattice-Ref`
|
|
3
|
+
* request header on every interactive request (GET and writes alike). This must
|
|
4
|
+
* match ComponentReferenceSigner::token() on the PHP side, which reads the same
|
|
5
|
+
* header.
|
|
6
|
+
*/
|
|
7
|
+
export declare const LATTICE_REF_HEADER = "X-Lattice-Ref";
|
|
8
|
+
export declare function withRefHeader(componentRef: string): Record<string, string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region resources/js/core/component-ref.ts
|
|
2
|
+
/**
|
|
3
|
+
* The signed component reference travels to the server as the `X-Lattice-Ref`
|
|
4
|
+
* request header on every interactive request (GET and writes alike). This must
|
|
5
|
+
* match ComponentReferenceSigner::token() on the PHP side, which reads the same
|
|
6
|
+
* header.
|
|
7
|
+
*/
|
|
8
|
+
var LATTICE_REF_HEADER = "X-Lattice-Ref";
|
|
9
|
+
function withRefHeader(componentRef) {
|
|
10
|
+
return componentRef ? { [LATTICE_REF_HEADER]: componentRef } : {};
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { LATTICE_REF_HEADER, withRefHeader };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=component-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-ref.js","names":[],"sources":["../../resources/js/core/component-ref.ts"],"sourcesContent":["/**\n * The signed component reference travels to the server as the `X-Lattice-Ref`\n * request header on every interactive request (GET and writes alike). This must\n * match ComponentReferenceSigner::token() on the PHP side, which reads the same\n * header.\n */\nexport const LATTICE_REF_HEADER = \"X-Lattice-Ref\";\n\nexport function withRefHeader(componentRef: string): Record<string, string> {\n return componentRef ? { [LATTICE_REF_HEADER]: componentRef } : {};\n}\n"],"mappings":";;;;;;;AAMA,IAAa,qBAAqB;AAElC,SAAgB,cAAc,cAA8C;CAC1E,OAAO,eAAe,GAAG,qBAAqB,aAAa,IAAI,CAAC;AAClE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { VariantProps } from 'class-variance-authority';
|
|
2
|
+
import { RendererComponent } from '../../../../core/types';
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
declare const badgeVariants: (props?: ({
|
|
5
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
|
|
6
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
|
+
declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}): React.JSX.Element;
|
|
10
|
+
declare module '../../../../core/types' {
|
|
11
|
+
interface ComponentProps {
|
|
12
|
+
badge: {
|
|
13
|
+
label?: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
declare const BadgeComponent: RendererComponent<"badge">;
|
|
18
|
+
export default BadgeComponent;
|
|
19
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { cn } from "../../lib/utils.js";
|
|
2
|
+
import { getStringProp } from "../props.js";
|
|
3
|
+
import "react";
|
|
4
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
//#region resources/js/core/components/badge.tsx
|
|
8
|
+
var badgeVariants = cva("inline-flex items-center justify-center rounded-lt-sm border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-lt-ring focus-visible:ring-lt-ring/50 focus-visible:ring-[3px] aria-invalid:ring-lt-danger/20 dark:aria-invalid:ring-lt-danger/40 aria-invalid:border-lt-danger transition-[color,box-shadow] overflow-hidden", {
|
|
9
|
+
variants: { variant: {
|
|
10
|
+
default: "border-transparent bg-lt-primary text-lt-primary-fg [a&]:hover:bg-lt-primary/90",
|
|
11
|
+
secondary: "border-transparent bg-lt-secondary text-lt-secondary-fg [a&]:hover:bg-lt-secondary/90",
|
|
12
|
+
destructive: "border-transparent bg-lt-danger text-lt-danger-fg [a&]:hover:bg-lt-danger/90 focus-visible:ring-lt-danger/20 dark:focus-visible:ring-lt-danger/40 dark:bg-lt-danger/60",
|
|
13
|
+
outline: "border-lt-border text-lt-fg [a&]:hover:bg-lt-accent [a&]:hover:text-lt-accent-fg"
|
|
14
|
+
} },
|
|
15
|
+
defaultVariants: { variant: "default" }
|
|
16
|
+
});
|
|
17
|
+
function Badge({ className, variant, asChild = false, ...props }) {
|
|
18
|
+
return /* @__PURE__ */ jsx(asChild ? Slot : "span", {
|
|
19
|
+
"data-slot": "badge",
|
|
20
|
+
className: cn(badgeVariants({ variant }), className),
|
|
21
|
+
...props
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
var BadgeComponent = ({ node }) => /* @__PURE__ */ jsx(Badge, {
|
|
25
|
+
variant: "secondary",
|
|
26
|
+
className: "w-fit px-3 py-1",
|
|
27
|
+
children: getStringProp(node.props, "label")
|
|
28
|
+
});
|
|
29
|
+
//#endregion
|
|
30
|
+
export { Badge, badgeVariants, BadgeComponent as default };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.js","names":[],"sources":["../../../resources/js/core/components/badge.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@lattice/lattice/lib/utils\";\nimport { getStringProp } from \"@lattice/lattice/core/props\";\nimport type { RendererComponent } from \"@lattice/lattice/core/types\";\n\nconst badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-lt-sm border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-lt-ring focus-visible:ring-lt-ring/50 focus-visible:ring-[3px] aria-invalid:ring-lt-danger/20 dark:aria-invalid:ring-lt-danger/40 aria-invalid:border-lt-danger transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default: \"border-transparent bg-lt-primary text-lt-primary-fg [a&]:hover:bg-lt-primary/90\",\n secondary:\n \"border-transparent bg-lt-secondary text-lt-secondary-fg [a&]:hover:bg-lt-secondary/90\",\n destructive:\n \"border-transparent bg-lt-danger text-lt-danger-fg [a&]:hover:bg-lt-danger/90 focus-visible:ring-lt-danger/20 dark:focus-visible:ring-lt-danger/40 dark:bg-lt-danger/60\",\n outline: \"border-lt-border text-lt-fg [a&]:hover:bg-lt-accent [a&]:hover:text-lt-accent-fg\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"span\";\n\n return (\n <Comp data-slot=\"badge\" className={cn(badgeVariants({ variant }), className)} {...props} />\n );\n}\n\ndeclare module \"@lattice/lattice/core/types\" {\n interface ComponentProps {\n badge: {\n label?: string;\n };\n }\n}\n\nconst BadgeComponent: RendererComponent<\"badge\"> = ({ node }) => (\n <Badge variant=\"secondary\" className=\"w-fit px-3 py-1\">\n {getStringProp(node.props, \"label\")}\n </Badge>\n);\n\nexport default BadgeComponent;\nexport { Badge, badgeVariants };\n"],"mappings":";;;;;;;AAOA,IAAM,gBAAgB,IACpB,qZACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,WACE;EACF,aACE;EACF,SAAS;CACX,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,SAAS,MAAM,EACb,WACA,SACA,UAAU,OACV,GAAG,SACyF;CAG5F,OACE,oBAHW,UAAU,OAAO,QAG5B;EAAM,aAAU;EAAQ,WAAW,GAAG,cAAc,EAAE,QAAQ,CAAC,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAE9F;AAUA,IAAM,kBAA8C,EAAE,WACpD,oBAAC,OAAD;CAAO,SAAQ;CAAY,WAAU;WAClC,cAAc,KAAK,OAAO,OAAO;AAC7B,CAAA"}
|