@pglevy/sailwind 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/README.md +219 -0
- package/dist/components/Button/ButtonArrayLayout.d.ts +37 -0
- package/dist/components/Button/ButtonArrayLayout.d.ts.map +1 -0
- package/dist/components/Button/ButtonArrayLayout.js +42 -0
- package/dist/components/Button/ButtonWidget.d.ts +75 -0
- package/dist/components/Button/ButtonWidget.d.ts.map +1 -0
- package/dist/components/Button/ButtonWidget.js +101 -0
- package/dist/components/Button/index.d.ts +5 -0
- package/dist/components/Button/index.d.ts.map +1 -0
- package/dist/components/Card/CardLayout.d.ts +55 -0
- package/dist/components/Card/CardLayout.d.ts.map +1 -0
- package/dist/components/Card/CardLayout.js +139 -0
- package/dist/components/Card/index.d.ts +3 -0
- package/dist/components/Card/index.d.ts.map +1 -0
- package/dist/components/Checkbox/CheckboxField.d.ts +65 -0
- package/dist/components/Checkbox/CheckboxField.d.ts.map +1 -0
- package/dist/components/Checkbox/CheckboxField.js +136 -0
- package/dist/components/Checkbox/index.d.ts +3 -0
- package/dist/components/Checkbox/index.d.ts.map +1 -0
- package/dist/components/Dialog/DialogField.d.ts +51 -0
- package/dist/components/Dialog/DialogField.d.ts.map +1 -0
- package/dist/components/Dialog/DialogField.js +113 -0
- package/dist/components/Dialog/index.d.ts +3 -0
- package/dist/components/Dialog/index.d.ts.map +1 -0
- package/dist/components/Dropdown/DropdownField.d.ts +87 -0
- package/dist/components/Dropdown/DropdownField.d.ts.map +1 -0
- package/dist/components/Dropdown/DropdownField.js +7 -0
- package/dist/components/Dropdown/DropdownFieldBase.d.ts +54 -0
- package/dist/components/Dropdown/DropdownFieldBase.d.ts.map +1 -0
- package/dist/components/Dropdown/DropdownFieldBase.js +183 -0
- package/dist/components/Dropdown/MultipleDropdownField.d.ts +85 -0
- package/dist/components/Dropdown/MultipleDropdownField.d.ts.map +1 -0
- package/dist/components/Dropdown/MultipleDropdownField.js +7 -0
- package/dist/components/Dropdown/index.d.ts +5 -0
- package/dist/components/Dropdown/index.d.ts.map +1 -0
- package/dist/components/Heading/HeadingField.d.ts +48 -0
- package/dist/components/Heading/HeadingField.d.ts.map +1 -0
- package/dist/components/Heading/HeadingField.js +103 -0
- package/dist/components/Heading/index.d.ts +3 -0
- package/dist/components/Heading/index.d.ts.map +1 -0
- package/dist/components/Image/DocumentImage.d.ts +20 -0
- package/dist/components/Image/DocumentImage.d.ts.map +1 -0
- package/dist/components/Image/ImageField.d.ts +42 -0
- package/dist/components/Image/ImageField.d.ts.map +1 -0
- package/dist/components/Image/ImageField.js +159 -0
- package/dist/components/Image/UserImage.d.ts +49 -0
- package/dist/components/Image/UserImage.d.ts.map +1 -0
- package/dist/components/Image/index.d.ts +5 -0
- package/dist/components/Image/index.d.ts.map +1 -0
- package/dist/components/MessageBanner/MessageBanner.d.ts +33 -0
- package/dist/components/MessageBanner/MessageBanner.d.ts.map +1 -0
- package/dist/components/MessageBanner/MessageBanner.js +97 -0
- package/dist/components/MessageBanner/index.d.ts +2 -0
- package/dist/components/MessageBanner/index.d.ts.map +1 -0
- package/dist/components/Milestone/MilestoneField.d.ts +50 -0
- package/dist/components/Milestone/MilestoneField.d.ts.map +1 -0
- package/dist/components/Milestone/MilestoneField.js +206 -0
- package/dist/components/Milestone/index.d.ts +3 -0
- package/dist/components/Milestone/index.d.ts.map +1 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts +32 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts.map +1 -0
- package/dist/components/ProgressBar/ProgressBar.js +117 -0
- package/dist/components/ProgressBar/index.d.ts +2 -0
- package/dist/components/ProgressBar/index.d.ts.map +1 -0
- package/dist/components/RadioButton/RadioButtonField.d.ts +63 -0
- package/dist/components/RadioButton/RadioButtonField.d.ts.map +1 -0
- package/dist/components/RadioButton/RadioButtonField.js +128 -0
- package/dist/components/RadioButton/index.d.ts +3 -0
- package/dist/components/RadioButton/index.d.ts.map +1 -0
- package/dist/components/RichText/Icon.d.ts +28 -0
- package/dist/components/RichText/Icon.d.ts.map +1 -0
- package/dist/components/RichText/Icon.js +94 -0
- package/dist/components/RichText/RichTextDisplayField.d.ts +36 -0
- package/dist/components/RichText/RichTextDisplayField.d.ts.map +1 -0
- package/dist/components/RichText/RichTextDisplayField.js +79 -0
- package/dist/components/RichText/TextItem.d.ts +27 -0
- package/dist/components/RichText/TextItem.d.ts.map +1 -0
- package/dist/components/RichText/TextItem.js +58 -0
- package/dist/components/RichText/index.d.ts +7 -0
- package/dist/components/RichText/index.d.ts.map +1 -0
- package/dist/components/Slider/SliderField.d.ts +63 -0
- package/dist/components/Slider/SliderField.d.ts.map +1 -0
- package/dist/components/Slider/SliderField.js +164 -0
- package/dist/components/Slider/index.d.ts +3 -0
- package/dist/components/Slider/index.d.ts.map +1 -0
- package/dist/components/Stamp/StampField.d.ts +48 -0
- package/dist/components/Stamp/StampField.d.ts.map +1 -0
- package/dist/components/Stamp/StampField.js +173 -0
- package/dist/components/Stamp/index.d.ts +3 -0
- package/dist/components/Stamp/index.d.ts.map +1 -0
- package/dist/components/Switch/SwitchField.d.ts +49 -0
- package/dist/components/Switch/SwitchField.d.ts.map +1 -0
- package/dist/components/Switch/SwitchField.js +106 -0
- package/dist/components/Switch/index.d.ts +3 -0
- package/dist/components/Switch/index.d.ts.map +1 -0
- package/dist/components/TableOfContents.d.ts +2 -0
- package/dist/components/TableOfContents.d.ts.map +1 -0
- package/dist/components/TableOfContents.js +142 -0
- package/dist/components/Tabs/TabsField.d.ts +50 -0
- package/dist/components/Tabs/TabsField.d.ts.map +1 -0
- package/dist/components/Tabs/TabsField.js +96 -0
- package/dist/components/Tabs/index.d.ts +3 -0
- package/dist/components/Tabs/index.d.ts.map +1 -0
- package/dist/components/Tag/TagField.d.ts +52 -0
- package/dist/components/Tag/TagField.d.ts.map +1 -0
- package/dist/components/Tag/TagField.js +125 -0
- package/dist/components/Tag/TagItem.d.ts +26 -0
- package/dist/components/Tag/TagItem.d.ts.map +1 -0
- package/dist/components/Tag/TagItem.js +4 -0
- package/dist/components/Tag/index.d.ts +5 -0
- package/dist/components/Tag/index.d.ts.map +1 -0
- package/dist/components/TextField/TextField.d.ts +88 -0
- package/dist/components/TextField/TextField.d.ts.map +1 -0
- package/dist/components/TextField/TextField.js +113 -0
- package/dist/components/TextField/index.d.ts +3 -0
- package/dist/components/TextField/index.d.ts.map +1 -0
- package/dist/components/Toggle/ToggleField.d.ts +62 -0
- package/dist/components/Toggle/ToggleField.d.ts.map +1 -0
- package/dist/components/Toggle/ToggleField.js +126 -0
- package/dist/components/Toggle/index.d.ts +3 -0
- package/dist/components/Toggle/index.d.ts.map +1 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/shared/CollapsibleSection.d.ts +9 -0
- package/dist/components/shared/CollapsibleSection.d.ts.map +1 -0
- package/dist/components/shared/CollapsibleSection.js +39 -0
- package/dist/components/shared/FieldLabel.d.ts +27 -0
- package/dist/components/shared/FieldLabel.d.ts.map +1 -0
- package/dist/components/shared/FieldLabel.js +40 -0
- package/dist/components/shared/FieldWrapper.d.ts +35 -0
- package/dist/components/shared/FieldWrapper.d.ts.map +1 -0
- package/dist/components/shared/FieldWrapper.js +71 -0
- package/dist/components/shared/index.d.ts +6 -0
- package/dist/components/shared/index.d.ts.map +1 -0
- package/dist/esg_world_logo_no_year.png +0 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/types/sail.d.ts +37 -0
- package/dist/types/sail.d.ts.map +1 -0
- package/dist/uifaces-human-avatar.jpg +0 -0
- package/dist/utils/classNames.d.ts +21 -0
- package/dist/utils/classNames.d.ts.map +1 -0
- package/dist/utils/classNames.js +16 -0
- package/dist/vite.svg +1 -0
- package/package.json +85 -0
package/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Sailwind
|
|
2
|
+
|
|
3
|
+
**React component library for rapid prototyping of Appian applications with SAIL-compatible syntax.**
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Sailwind enables UX designers to rapidly prototype Appian applications using React and LLMs (like Claude) before committing to SAIL development. Components look like Appian, use exact SAIL parameter names, and translate directly to production code.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **SAIL-Exact Parameters** - Use UPPERCASE values matching SAIL: `size="STANDARD"` not `size="standard"`
|
|
12
|
+
- **Backwards Compatible** - React code translates almost directly to SAIL
|
|
13
|
+
- **LLM-Friendly** - Clear patterns for AI-assisted development
|
|
14
|
+
- **Accessible** - All components meet WCAG 2.1 AA standards
|
|
15
|
+
- **Production-Ready Foundation** - Built on Radix UI primitives + Tailwind CSS
|
|
16
|
+
|
|
17
|
+
## Quickstart
|
|
18
|
+
|
|
19
|
+
### Option 1: Use This Template (Recommended)
|
|
20
|
+
1. Click **"Use this template"** button above
|
|
21
|
+
2. Clone your new repository
|
|
22
|
+
3. Install dependencies: `npm install`
|
|
23
|
+
4. Start development server: `npm run dev`
|
|
24
|
+
5. Open `http://localhost:5173` to see the component library and examples
|
|
25
|
+
|
|
26
|
+
### Option 2: Clone Directly
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/pglevy/sailwind.git
|
|
29
|
+
cd sailwind
|
|
30
|
+
npm install
|
|
31
|
+
npm run dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Creating Your First Prototype
|
|
35
|
+
1. **Browse examples** at `/#/examples/taskdashboard` to see what's possible
|
|
36
|
+
2. **Explore components** at `/#/components` to understand available building blocks
|
|
37
|
+
3. **Create new pages** by adding `.tsx` files to `src/pages/` - they'll automatically become routes
|
|
38
|
+
4. **Import components** using exact SAIL parameter names:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// src/pages/my-prototype.tsx
|
|
42
|
+
import { CardLayout, HeadingField, TagField, ButtonArrayLayout } from '../components'
|
|
43
|
+
|
|
44
|
+
export default function MyPrototype() {
|
|
45
|
+
return (
|
|
46
|
+
<CardLayout padding="STANDARD">
|
|
47
|
+
<HeadingField text="My Prototype" size="LARGE" />
|
|
48
|
+
<TagField
|
|
49
|
+
tags={[{ text: "DRAFT", backgroundColor: "ACCENT" }]}
|
|
50
|
+
size="STANDARD"
|
|
51
|
+
/>
|
|
52
|
+
<ButtonArrayLayout
|
|
53
|
+
buttons={[
|
|
54
|
+
{ label: "Save", style: "SOLID", color: "ACCENT" },
|
|
55
|
+
{ label: "Cancel", style: "OUTLINE", color: "SECONDARY" }
|
|
56
|
+
]}
|
|
57
|
+
align="END"
|
|
58
|
+
/>
|
|
59
|
+
</CardLayout>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
4. **Navigate to** `/#/my-prototype` to see your page
|
|
65
|
+
5. **Translate to SAIL** when ready for production using the exact same parameter names
|
|
66
|
+
|
|
67
|
+
### Next Steps
|
|
68
|
+
- Check out `src/pages/examples/` for complete interface examples
|
|
69
|
+
- Read the component documentation below for detailed usage
|
|
70
|
+
- Use the table of contents on the home page to navigate between examples
|
|
71
|
+
|
|
72
|
+
## Component Comparison
|
|
73
|
+
|
|
74
|
+
**React Prototype:**
|
|
75
|
+
```tsx
|
|
76
|
+
<TagField
|
|
77
|
+
size="STANDARD"
|
|
78
|
+
tags={[
|
|
79
|
+
{ text: "URGENT", backgroundColor: "#FED7DE", textColor: "#9F0019" }
|
|
80
|
+
]}
|
|
81
|
+
/>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**SAIL Production:**
|
|
85
|
+
```sail
|
|
86
|
+
a!tagField(
|
|
87
|
+
size: "STANDARD",
|
|
88
|
+
tags: {
|
|
89
|
+
a!tagItem(text: "URGENT", backgroundColor: "#FED7DE", textColor: "#9F0019")
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Architecture
|
|
95
|
+
|
|
96
|
+
### Foundation Stack
|
|
97
|
+
- **Base:** Radix UI (unstyled, accessible primitives)
|
|
98
|
+
- **Styling:** Tailwind CSS with Aurora color palette
|
|
99
|
+
- **Language:** TypeScript (enforces SAIL conventions)
|
|
100
|
+
|
|
101
|
+
### Two-Layer Approach
|
|
102
|
+
|
|
103
|
+
Sailwind uses a clear separation:
|
|
104
|
+
|
|
105
|
+
1. **Layer 1: SAIL API** - Component props use SAIL parameter names (UPPERCASE values)
|
|
106
|
+
2. **Layer 2: Implementation** - Standard Tailwind classes for styling
|
|
107
|
+
|
|
108
|
+
## Icon Library
|
|
109
|
+
|
|
110
|
+
Sailwind uses **Lucide React** for icons with simplified names that map to SAIL:
|
|
111
|
+
|
|
112
|
+
| React Icon | SAIL Icon | Lucide Component |
|
|
113
|
+
|------------|-----------|------------------|
|
|
114
|
+
| "info" | "info-circle" | Info |
|
|
115
|
+
| "success" | "check-circle" | CheckCircle |
|
|
116
|
+
| "warning" | "exclamation-triangle" | AlertTriangle |
|
|
117
|
+
| "error" | "exclamation-circle" | AlertCircle |
|
|
118
|
+
|
|
119
|
+
## Styling Approach
|
|
120
|
+
|
|
121
|
+
Sailwind uses **standard Tailwind classes** internally while maintaining SAIL-exact component APIs:
|
|
122
|
+
|
|
123
|
+
### Text Sizes
|
|
124
|
+
- **SMALL** → `text-xs` (12px)
|
|
125
|
+
- **STANDARD** → `text-base` (16px)
|
|
126
|
+
- **MEDIUM** → `text-lg` (18px)
|
|
127
|
+
- **LARGE** → `text-2xl` (24px)
|
|
128
|
+
|
|
129
|
+
### Spacing
|
|
130
|
+
- **NONE** → `p-0` / `m-0` (0)
|
|
131
|
+
- **EVEN_LESS** → `p-1` / `m-1` (4px)
|
|
132
|
+
- **LESS** → `p-2` / `m-2` (8px)
|
|
133
|
+
- **STANDARD** → `p-4` / `m-4` (16px)
|
|
134
|
+
- **MORE** → `p-6` / `m-6` (24px)
|
|
135
|
+
- **EVEN_MORE** → `p-8` / `m-8` (32px)
|
|
136
|
+
|
|
137
|
+
### Aurora Color Palette
|
|
138
|
+
|
|
139
|
+
All colors use consistent Tailwind steps: **50, 100, 200, 500, 700, 900**
|
|
140
|
+
|
|
141
|
+
**Available colors:** `red`, `orange`, `yellow`, `green`, `teal`, `sky`, `blue`, `purple`, `pink`, `gray`
|
|
142
|
+
|
|
143
|
+
**Usage:**
|
|
144
|
+
```tsx
|
|
145
|
+
// Light backgrounds
|
|
146
|
+
<div className="bg-blue-100 text-blue-700">Tag</div>
|
|
147
|
+
|
|
148
|
+
// Primary actions
|
|
149
|
+
<button className="bg-blue-500 hover:bg-blue-700">Submit</button>
|
|
150
|
+
|
|
151
|
+
// Text hierarchy
|
|
152
|
+
<h1 className="text-gray-900">Heading</h1>
|
|
153
|
+
<p className="text-gray-700">Body</p>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Semantic Colors
|
|
157
|
+
|
|
158
|
+
| Semantic | Usage | Tailwind |
|
|
159
|
+
|----------|-------|----------|
|
|
160
|
+
| ACCENT | Primary actions | `blue-500` |
|
|
161
|
+
| POSITIVE | Success states | `green-700` |
|
|
162
|
+
| NEGATIVE | Error states | `red-700` |
|
|
163
|
+
| SECONDARY | Secondary actions | `gray-700` |
|
|
164
|
+
| STANDARD | Default text | `gray-900` |
|
|
165
|
+
|
|
166
|
+
## Development
|
|
167
|
+
|
|
168
|
+
### Available Scripts
|
|
169
|
+
|
|
170
|
+
- `npm run dev` - Start development server with HMR
|
|
171
|
+
- `npm run build` - Build for production
|
|
172
|
+
- `npm run lint` - Run ESLint
|
|
173
|
+
- `npm run preview` - Preview production build
|
|
174
|
+
|
|
175
|
+
### Project Structure
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
sailwind/
|
|
179
|
+
├── src/
|
|
180
|
+
│ ├── components/ # SAIL components (Button, Tag, Card, etc.)
|
|
181
|
+
│ ├── types/ # Shared TypeScript types (SAILSize, SAILAlign, etc.)
|
|
182
|
+
│ ├── index.css # Tailwind v4 theme configuration
|
|
183
|
+
│ └── App.tsx # Demo/playground
|
|
184
|
+
├── TAILWIND-SAIL-MAPPING.md # Complete styling reference
|
|
185
|
+
├── CLAUDE.md # LLM instructions
|
|
186
|
+
└── package.json
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Documentation
|
|
190
|
+
|
|
191
|
+
- **[TAILWIND-SAIL-MAPPING.md](TAILWIND-SAIL-MAPPING.md)** - Complete reference for Tailwind to SAIL mappings
|
|
192
|
+
- **[CLAUDE.md](CLAUDE.md)** - Instructions for LLM-assisted development
|
|
193
|
+
- **[SAIL Official Docs](https://docs.appian.com/suite/help/25.3/)** - Appian SAIL reference
|
|
194
|
+
|
|
195
|
+
## Related Resources
|
|
196
|
+
|
|
197
|
+
- **Radix UI** - https://www.radix-ui.com/
|
|
198
|
+
- **Tailwind CSS** - https://tailwindcss.com/
|
|
199
|
+
- **Aurora Design System** - Color palette and branding
|
|
200
|
+
|
|
201
|
+
## Contributing
|
|
202
|
+
|
|
203
|
+
This is a proof-of-concept for rapid Appian prototyping. Contributions welcome!
|
|
204
|
+
|
|
205
|
+
### Guidelines
|
|
206
|
+
|
|
207
|
+
1. Use exact SAIL parameter names (UPPERCASE values)
|
|
208
|
+
2. Follow Item + Field component pattern
|
|
209
|
+
3. Include SAIL translation examples in documentation
|
|
210
|
+
4. Ensure WCAG 2.1 AA accessibility compliance
|
|
211
|
+
5. Use standard Tailwind classes internally
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
TBD
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
**Status:** Active development - 20 components implemented (15 SAIL + 5 "New SAIL") including form inputs, selections, toggles, sliders, tabs, dialogs, and display components
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ButtonWidgetProps } from './ButtonWidget';
|
|
2
|
+
import { SAILAlign, SAILMarginSize } from '../../types/sail';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Props for the ButtonArrayLayout component
|
|
6
|
+
* Maps to SAIL's a!buttonArrayLayout() function
|
|
7
|
+
*/
|
|
8
|
+
export interface ButtonArrayLayoutProps {
|
|
9
|
+
/** Array of button configurations */
|
|
10
|
+
buttons: ButtonWidgetProps[];
|
|
11
|
+
/** Controls layout visibility */
|
|
12
|
+
showWhen?: boolean;
|
|
13
|
+
/** Determines alignment of buttons */
|
|
14
|
+
align?: SAILAlign;
|
|
15
|
+
/** Space added below the buttons */
|
|
16
|
+
marginBelow?: SAILMarginSize;
|
|
17
|
+
/** Additional text for screen readers */
|
|
18
|
+
accessibilityText?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* ButtonArrayLayout Component
|
|
22
|
+
* Displays a list of buttons in the order they are specified
|
|
23
|
+
*
|
|
24
|
+
* In SAIL, a!buttonWidget must be used within a!buttonArrayLayout.
|
|
25
|
+
* This component wraps buttons and provides layout/alignment.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* <ButtonArrayLayout
|
|
29
|
+
* align="END"
|
|
30
|
+
* buttons={[
|
|
31
|
+
* { label: "Cancel", style: "OUTLINE", color: "SECONDARY" },
|
|
32
|
+
* { label: "Submit", style: "SOLID", color: "ACCENT", submit: true }
|
|
33
|
+
* ]}
|
|
34
|
+
* />
|
|
35
|
+
*/
|
|
36
|
+
export declare const ButtonArrayLayout: React.FC<ButtonArrayLayoutProps>;
|
|
37
|
+
//# sourceMappingURL=ButtonArrayLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ButtonArrayLayout.d.ts","sourceRoot":"","sources":["../../../src/components/Button/ButtonArrayLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAEvD,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjE;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sCAAsC;IACtC,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,oCAAoC;IACpC,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA6C9D,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import { ButtonWidget as E } from "./ButtonWidget.js";
|
|
4
|
+
const g = ({
|
|
5
|
+
buttons: i,
|
|
6
|
+
showWhen: n = !0,
|
|
7
|
+
align: o = "START",
|
|
8
|
+
marginBelow: l = "STANDARD",
|
|
9
|
+
accessibilityText: s
|
|
10
|
+
}) => {
|
|
11
|
+
if (!n) return null;
|
|
12
|
+
const e = i.filter((t) => t.showWhen !== !1), a = {
|
|
13
|
+
START: "justify-start",
|
|
14
|
+
CENTER: "justify-center",
|
|
15
|
+
END: "justify-end"
|
|
16
|
+
}, f = {
|
|
17
|
+
NONE: "mb-0",
|
|
18
|
+
// SAIL NONE: 0
|
|
19
|
+
EVEN_LESS: "mb-1",
|
|
20
|
+
// SAIL EVEN_LESS: 4px
|
|
21
|
+
LESS: "mb-2",
|
|
22
|
+
// SAIL LESS: 8px
|
|
23
|
+
STANDARD: "mb-4",
|
|
24
|
+
// SAIL STANDARD: 16px
|
|
25
|
+
MORE: "mb-6",
|
|
26
|
+
// SAIL MORE: 24px
|
|
27
|
+
EVEN_MORE: "mb-8"
|
|
28
|
+
// SAIL EVEN_MORE: 32px
|
|
29
|
+
}, m = e.length === 1 ? "END" : "START";
|
|
30
|
+
return /* @__PURE__ */ r(
|
|
31
|
+
"div",
|
|
32
|
+
{
|
|
33
|
+
className: `flex flex-wrap gap-4 items-start ${a[o || m]} ${f[l]}`,
|
|
34
|
+
role: "group",
|
|
35
|
+
"aria-label": s,
|
|
36
|
+
children: e.map((t, u) => /* @__PURE__ */ r(E, { ...t }, u))
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
export {
|
|
41
|
+
g as ButtonArrayLayout
|
|
42
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { SAILSize } from '../../types/sail';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
type ButtonStyle = "SOLID" | "OUTLINE" | "GHOST" | "LINK";
|
|
4
|
+
type ButtonColor = "ACCENT" | "NEGATIVE" | "SECONDARY";
|
|
5
|
+
type ButtonWidth = "MINIMIZE" | "FILL";
|
|
6
|
+
type IconPosition = "START" | "END";
|
|
7
|
+
/**
|
|
8
|
+
* Props for the ButtonWidget component
|
|
9
|
+
* Maps to SAIL's a!buttonWidget() function
|
|
10
|
+
*/
|
|
11
|
+
export interface ButtonWidgetProps {
|
|
12
|
+
/** Text to display on the button */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Determines the button's appearance */
|
|
15
|
+
style?: ButtonStyle;
|
|
16
|
+
/** Determines button color (hex or semantic) */
|
|
17
|
+
color?: ButtonColor | string;
|
|
18
|
+
/** Determines size of the button */
|
|
19
|
+
size?: SAILSize;
|
|
20
|
+
/** Determines button width */
|
|
21
|
+
width?: ButtonWidth;
|
|
22
|
+
/** Prevents user from clicking the button */
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/** Whether this button submits a form */
|
|
25
|
+
submit?: boolean;
|
|
26
|
+
/** Determines whether button performs validation */
|
|
27
|
+
validate?: boolean;
|
|
28
|
+
/** Validation group identifier */
|
|
29
|
+
validationGroup?: string;
|
|
30
|
+
/** Text for confirmation dialog */
|
|
31
|
+
confirmMessage?: string;
|
|
32
|
+
/** Text for confirmation dialog header */
|
|
33
|
+
confirmHeader?: string;
|
|
34
|
+
/** Text for confirmation button */
|
|
35
|
+
confirmButtonLabel?: string;
|
|
36
|
+
/** Text for cancel button */
|
|
37
|
+
cancelButtonLabel?: string;
|
|
38
|
+
/** Controls button visibility */
|
|
39
|
+
showWhen?: boolean;
|
|
40
|
+
/** Icon to display */
|
|
41
|
+
icon?: string;
|
|
42
|
+
/** Position of icon */
|
|
43
|
+
iconPosition?: IconPosition;
|
|
44
|
+
/** Additional text for screen readers */
|
|
45
|
+
accessibilityText?: string;
|
|
46
|
+
/** Tooltip text on hover */
|
|
47
|
+
tooltip?: string;
|
|
48
|
+
/** Loading indicator on press */
|
|
49
|
+
loadingIndicator?: boolean;
|
|
50
|
+
/** Value associated with this button */
|
|
51
|
+
value?: any;
|
|
52
|
+
/** Click handler (maps to saveInto in SAIL) */
|
|
53
|
+
saveInto?: (value?: any) => void;
|
|
54
|
+
/** Click handler (React-style alias for saveInto) */
|
|
55
|
+
onClick?: (value?: any) => void;
|
|
56
|
+
/** Additional Tailwind classes for prototype-specific styling (not part of SAIL API) */
|
|
57
|
+
className?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* ButtonWidget Component
|
|
61
|
+
* Displays a button that can conditionally be used to submit a form
|
|
62
|
+
*
|
|
63
|
+
* Note: In SAIL, a!buttonWidget must be used within a!buttonArrayLayout.
|
|
64
|
+
* For standalone use in React, wrap with ButtonArrayLayout component.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* <ButtonArrayLayout
|
|
68
|
+
* buttons={[
|
|
69
|
+
* { label: "Submit", style: "SOLID", color: "ACCENT" }
|
|
70
|
+
* ]}
|
|
71
|
+
* />
|
|
72
|
+
*/
|
|
73
|
+
export declare const ButtonWidget: React.FC<ButtonWidgetProps>;
|
|
74
|
+
export {};
|
|
75
|
+
//# sourceMappingURL=ButtonWidget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ButtonWidget.d.ts","sourceRoot":"","sources":["../../../src/components/Button/ButtonWidget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGhD,KAAK,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;AACzD,KAAK,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAA;AACtD,KAAK,WAAW,GAAG,UAAU,GAAG,MAAM,CAAA;AACtC,KAAK,YAAY,GAAG,OAAO,GAAG,KAAK,CAAA;AAEnC;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yCAAyC;IACzC,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,gDAAgD;IAChD,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;IAC5B,oCAAoC;IACpC,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,8BAA8B;IAC9B,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yCAAyC;IACzC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,mCAAmC;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,6BAA6B;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sBAAsB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iCAAiC;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,wCAAwC;IACxC,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IAChC,qDAAqD;IACrD,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,wFAAwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgMpD,CAAA"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { jsxs as R, jsx as u } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import * as w from "lucide-react";
|
|
4
|
+
import { mergeClasses as M } from "../../utils/classNames.js";
|
|
5
|
+
const V = ({
|
|
6
|
+
label: i,
|
|
7
|
+
style: r = "OUTLINE",
|
|
8
|
+
color: t = "ACCENT",
|
|
9
|
+
size: b = "STANDARD",
|
|
10
|
+
width: d,
|
|
11
|
+
disabled: l = !1,
|
|
12
|
+
submit: p = !1,
|
|
13
|
+
showWhen: g = !0,
|
|
14
|
+
icon: a,
|
|
15
|
+
iconPosition: c = "START",
|
|
16
|
+
accessibilityText: h,
|
|
17
|
+
tooltip: E,
|
|
18
|
+
loadingIndicator: o = !1,
|
|
19
|
+
saveInto: A,
|
|
20
|
+
onClick: N,
|
|
21
|
+
value: x,
|
|
22
|
+
className: C
|
|
23
|
+
}) => {
|
|
24
|
+
if (!g) return null;
|
|
25
|
+
const m = {
|
|
26
|
+
SMALL: "px-3 py-1.5 text-sm",
|
|
27
|
+
// SAIL SMALL: 12px horizontal, 6px vertical
|
|
28
|
+
STANDARD: "px-4 py-2.5 text-base",
|
|
29
|
+
// SAIL STANDARD: 16px horizontal, 10px vertical
|
|
30
|
+
MEDIUM: "px-6 py-3 text-lg",
|
|
31
|
+
// SAIL MEDIUM: 24px horizontal, 12px vertical
|
|
32
|
+
LARGE: "px-8 py-4 text-xl"
|
|
33
|
+
// SAIL LARGE: 32px horizontal, 16px vertical
|
|
34
|
+
}, T = d === "FILL" ? "w-full" : "w-auto", S = () => {
|
|
35
|
+
if (!t.startsWith("#")) return;
|
|
36
|
+
const e = {};
|
|
37
|
+
return r === "SOLID" ? (e.backgroundColor = t, e.borderColor = "transparent", e.color = "#ffffff") : r === "OUTLINE" ? (e.borderColor = t, e.color = t, e.backgroundColor = "#ffffff") : (r === "GHOST" || r === "LINK") && (e.color = t, e.borderColor = "transparent"), Object.keys(e).length > 0 ? e : void 0;
|
|
38
|
+
}, L = () => {
|
|
39
|
+
if (t.startsWith("#"))
|
|
40
|
+
return r === "OUTLINE" ? "border-2" : "";
|
|
41
|
+
const e = t;
|
|
42
|
+
return r === "SOLID" ? {
|
|
43
|
+
ACCENT: "bg-blue-500 text-white hover:bg-blue-700",
|
|
44
|
+
NEGATIVE: "bg-red-700 text-white hover:bg-red-900",
|
|
45
|
+
SECONDARY: "bg-gray-700 text-white hover:bg-gray-900"
|
|
46
|
+
}[e] : r === "OUTLINE" ? {
|
|
47
|
+
ACCENT: "border-2 border-blue-500 text-blue-500 bg-white hover:bg-blue-100",
|
|
48
|
+
NEGATIVE: "border-2 border-red-700 text-red-700 bg-white hover:bg-red-100",
|
|
49
|
+
SECONDARY: "border-2 border-gray-700 text-gray-700 bg-white hover:bg-gray-100"
|
|
50
|
+
}[e] : r === "GHOST" ? {
|
|
51
|
+
ACCENT: "text-blue-500 hover:bg-blue-100",
|
|
52
|
+
NEGATIVE: "text-red-700 hover:bg-red-100",
|
|
53
|
+
SECONDARY: "text-gray-700 hover:bg-gray-100"
|
|
54
|
+
}[e] : r === "LINK" ? {
|
|
55
|
+
ACCENT: "text-blue-500 hover:underline",
|
|
56
|
+
NEGATIVE: "text-red-700 hover:underline",
|
|
57
|
+
SECONDARY: "text-gray-700 hover:underline"
|
|
58
|
+
}[e] : "";
|
|
59
|
+
}, I = () => r === "OUTLINE" || C ? "" : "border-2 border-transparent", D = `
|
|
60
|
+
inline-flex items-center justify-center gap-1
|
|
61
|
+
font-medium transition-colors h-auto rounded-sm
|
|
62
|
+
${m[b]}
|
|
63
|
+
${T}
|
|
64
|
+
${I()}
|
|
65
|
+
${L()}
|
|
66
|
+
${l || o ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
67
|
+
`.replace(/\s+/g, " ").trim(), v = M(D, C), O = () => {
|
|
68
|
+
const e = N || A;
|
|
69
|
+
e && !l && !o && e(x);
|
|
70
|
+
}, s = (() => {
|
|
71
|
+
if (!a) return null;
|
|
72
|
+
const e = a.split("-").map((f) => f.charAt(0).toUpperCase() + f.slice(1)).join(""), n = w[e];
|
|
73
|
+
return n ? /* @__PURE__ */ u(n, { size: {
|
|
74
|
+
SMALL: 14,
|
|
75
|
+
STANDARD: 16,
|
|
76
|
+
MEDIUM: 18,
|
|
77
|
+
LARGE: 20
|
|
78
|
+
}[b], "aria-hidden": "true" }) : (console.warn(`Icon "${a}" not found in Lucide icons`), null);
|
|
79
|
+
})(), y = S();
|
|
80
|
+
return /* @__PURE__ */ R(
|
|
81
|
+
"button",
|
|
82
|
+
{
|
|
83
|
+
type: p ? "submit" : "button",
|
|
84
|
+
onClick: O,
|
|
85
|
+
disabled: l || o,
|
|
86
|
+
className: v,
|
|
87
|
+
style: y,
|
|
88
|
+
"aria-label": h || i,
|
|
89
|
+
title: E,
|
|
90
|
+
children: [
|
|
91
|
+
o && /* @__PURE__ */ u("span", { className: "animate-spin", "aria-label": "loading", children: "⟳" }),
|
|
92
|
+
!o && s && c === "START" && s,
|
|
93
|
+
i && /* @__PURE__ */ u("span", { children: i }),
|
|
94
|
+
!o && s && c === "END" && s
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
export {
|
|
100
|
+
V as ButtonWidget
|
|
101
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Button/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SAILShape, SAILPadding, SAILMarginSize } from '../../types/sail';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
type CardHeight = "AUTO" | "SHORT" | "MEDIUM" | "TALL" | "EXTRA_TALL";
|
|
4
|
+
type CardStyle = "NONE" | "TRANSPARENT" | "STANDARD" | "ACCENT" | "SUCCESS" | "WARN" | "ERROR" | "INFO" | "CHARCOAL_SCHEME" | "NAVY_SCHEME" | "PLUM_SCHEME";
|
|
5
|
+
type DecorativeBarPosition = "TOP" | "START" | "NONE";
|
|
6
|
+
/**
|
|
7
|
+
* Props for the CardLayout component
|
|
8
|
+
* Maps to SAIL's a!cardLayout() function
|
|
9
|
+
*/
|
|
10
|
+
export interface CardLayoutProps {
|
|
11
|
+
/** Content to display inside the card */
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
/** Determines the height of the card */
|
|
14
|
+
height?: CardHeight;
|
|
15
|
+
/** Determines the card background color. Valid values: Any hex color (including transparency with 8 digits), or semantic values */
|
|
16
|
+
style?: CardStyle | string;
|
|
17
|
+
/** Determines the border radius */
|
|
18
|
+
shape?: SAILShape;
|
|
19
|
+
/** Determines the padding inside the card */
|
|
20
|
+
padding?: SAILPadding;
|
|
21
|
+
/** Space added above the card */
|
|
22
|
+
marginAbove?: SAILMarginSize;
|
|
23
|
+
/** Space added below the card */
|
|
24
|
+
marginBelow?: SAILMarginSize;
|
|
25
|
+
/** Whether to show card border */
|
|
26
|
+
showBorder?: boolean;
|
|
27
|
+
/** Whether to show card shadow */
|
|
28
|
+
showShadow?: boolean;
|
|
29
|
+
/** Determines the border color. Valid values: Any hex color (including transparency), or "STANDARD" (default), "ACCENT", "POSITIVE", "WARN", "NEGATIVE" */
|
|
30
|
+
borderColor?: string;
|
|
31
|
+
/** Position of decorative bar */
|
|
32
|
+
decorativeBarPosition?: DecorativeBarPosition;
|
|
33
|
+
/** Color of decorative bar (hex or semantic) */
|
|
34
|
+
decorativeBarColor?: string;
|
|
35
|
+
/** Controls card visibility */
|
|
36
|
+
showWhen?: boolean;
|
|
37
|
+
/** Additional Tailwind classes for prototype-specific styling (not part of SAIL API) */
|
|
38
|
+
className?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* CardLayout Component
|
|
42
|
+
* Displays content within a card container
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* <CardLayout
|
|
46
|
+
* shape="SEMI_ROUNDED"
|
|
47
|
+
* padding="STANDARD"
|
|
48
|
+
* showBorder={true}
|
|
49
|
+
* >
|
|
50
|
+
* <p>Card content here</p>
|
|
51
|
+
* </CardLayout>
|
|
52
|
+
*/
|
|
53
|
+
export declare const CardLayout: React.FC<CardLayoutProps>;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=CardLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CardLayout.d.ts","sourceRoot":"","sources":["../../../src/components/Card/CardLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAG9E,KAAK,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAA;AACrE,KAAK,SAAS,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,iBAAiB,GAAG,aAAa,GAAG,aAAa,CAAA;AAC3J,KAAK,qBAAqB,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAA;AAErD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,wCAAwC;IACxC,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,mIAAmI;IACnI,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC1B,mCAAmC;IACnC,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,iCAAiC;IACjC,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B,iCAAiC;IACjC,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B,kCAAkC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,kCAAkC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,2JAA2J;IAC3J,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iCAAiC;IACjC,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,gDAAgD;IAChD,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wFAAwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA6LhD,CAAA"}
|