@effigy-analytics/morass 0.2.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 +21 -0
- package/README.md +84 -0
- package/dist/components.d.ts +67 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/morass.cjs +1 -0
- package/dist/morass.js +193 -0
- package/dist/reminders.cjs +1 -0
- package/dist/reminders.d.ts +5 -0
- package/dist/reminders.d.ts.map +1 -0
- package/dist/reminders.js +18 -0
- package/dist/styles.css +2 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kevin Blum
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Morass
|
|
2
|
+
|
|
3
|
+
Morass is a small React UI framework for durable product interfaces: app shells, dense dashboards, forms, modal workflows, and status-heavy operational views.
|
|
4
|
+
|
|
5
|
+
Morass is the standard UI package for the Effigy Analytics suite. It was born inside Webbery, but its public API is generic: primitives only, no product domain logic in the root export.
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
- TypeScript React package, MIT licensed
|
|
10
|
+
- Vite library build
|
|
11
|
+
- CSS token system
|
|
12
|
+
- Accessible primitives for shell, cards, controls, tabs, modals, progress, and status
|
|
13
|
+
- CI-ready lint, typecheck, test, and build scripts
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
The package is published to GitHub Packages under the `@effigy-analytics` scope. GitHub Packages requires authentication to install, even for public packages — consumers need an `.npmrc` pointing the scope at the registry and a token with `read:packages`:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
@effigy-analytics:registry=https://npm.pkg.github.com
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @effigy-analytics/morass
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Development
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install
|
|
31
|
+
npm run check
|
|
32
|
+
npm run build
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Public API
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { AppFrame, Button, Card, StatusPill } from "@effigy-analytics/morass";
|
|
39
|
+
import "@effigy-analytics/morass/styles.css";
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Primitives: `AppFrame`, `Button`, `Card`, `TextField`, `SelectField`, `StatusPill`, `Metric`, `Tabs`, `ProgressSteps`, `Modal`, plus shared tone/utility helpers.
|
|
43
|
+
|
|
44
|
+
Morass ships unopinionated class names and CSS variables. Applications can override tokens at `:root` or inside a scoped theme container.
|
|
45
|
+
|
|
46
|
+
### Subpath: reminders
|
|
47
|
+
|
|
48
|
+
Due-date presentation helpers (`DueState`, `getDueStateTone`, `formatRelativeDue`) live behind a subpath export so the root API stays purely generic:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import {
|
|
52
|
+
formatRelativeDue,
|
|
53
|
+
getDueStateTone,
|
|
54
|
+
} from "@effigy-analytics/morass/reminders";
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Moved out of the root export in 0.2.0.
|
|
58
|
+
|
|
59
|
+
## Release Boundary
|
|
60
|
+
|
|
61
|
+
Morass is consumed by Effigy Analytics products (Webbery today, the platform apps as they adopt it) as a versioned package. Treat these surfaces as public within a published version:
|
|
62
|
+
|
|
63
|
+
- exports from `@effigy-analytics/morass`
|
|
64
|
+
- exports from `@effigy-analytics/morass/reminders`
|
|
65
|
+
- `@effigy-analytics/morass/styles.css`
|
|
66
|
+
- CSS custom properties intended for application theming
|
|
67
|
+
- component semantics and required peer dependency ranges
|
|
68
|
+
|
|
69
|
+
Breaking changes require a coordinated consumer update and a major version or explicit release note (pre-1.0, breaking changes ride minor versions and are called out in release notes). Consumers should pin Morass to a published version instead of depending on a live sibling checkout.
|
|
70
|
+
|
|
71
|
+
Before publishing:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm run check
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`npm run check` includes `npm pack --dry-run` after the library build, so CI
|
|
78
|
+
verifies the publishable package contents before a release. Then publish through
|
|
79
|
+
the GitHub Actions `Publish` workflow from a GitHub release whose tag matches
|
|
80
|
+
`v<package.json version>`.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, HTMLAttributes, InputHTMLAttributes, LabelHTMLAttributes, ReactNode, SelectHTMLAttributes } from "react";
|
|
2
|
+
import { type Tone } from "./utils";
|
|
3
|
+
export type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
|
|
4
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
variant?: ButtonVariant;
|
|
7
|
+
}
|
|
8
|
+
export declare function Button({ children, className, icon, type, variant, ...props }: ButtonProps): import("react").JSX.Element;
|
|
9
|
+
export interface CardProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
|
|
10
|
+
actions?: ReactNode;
|
|
11
|
+
eyebrow?: ReactNode;
|
|
12
|
+
title?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export declare function Card({ actions, children, className, eyebrow, title, ...props }: CardProps): import("react").JSX.Element;
|
|
15
|
+
export interface AppFrameProps {
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
header?: ReactNode;
|
|
18
|
+
nav?: ReactNode;
|
|
19
|
+
sidebar?: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export declare function AppFrame({ children, header, nav, sidebar }: AppFrameProps): import("react").JSX.Element;
|
|
22
|
+
export interface FieldProps {
|
|
23
|
+
error?: ReactNode;
|
|
24
|
+
helpText?: ReactNode;
|
|
25
|
+
label: ReactNode;
|
|
26
|
+
labelProps?: LabelHTMLAttributes<HTMLLabelElement>;
|
|
27
|
+
}
|
|
28
|
+
export interface TextFieldProps extends InputHTMLAttributes<HTMLInputElement>, FieldProps {
|
|
29
|
+
}
|
|
30
|
+
export declare function TextField({ error, helpText, label, labelProps, ...props }: TextFieldProps): import("react").JSX.Element;
|
|
31
|
+
export interface SelectFieldProps extends SelectHTMLAttributes<HTMLSelectElement>, FieldProps {
|
|
32
|
+
}
|
|
33
|
+
export declare function SelectField({ children, error, helpText, label, labelProps, ...props }: SelectFieldProps): import("react").JSX.Element;
|
|
34
|
+
export interface StatusPillProps {
|
|
35
|
+
children: ReactNode;
|
|
36
|
+
tone?: Tone;
|
|
37
|
+
}
|
|
38
|
+
export declare function StatusPill({ children, tone }: StatusPillProps): import("react").JSX.Element;
|
|
39
|
+
export interface MetricProps {
|
|
40
|
+
label: ReactNode;
|
|
41
|
+
value: ReactNode;
|
|
42
|
+
}
|
|
43
|
+
export declare function Metric({ label, value }: MetricProps): import("react").JSX.Element;
|
|
44
|
+
export interface TabsProps<TValue extends string> {
|
|
45
|
+
"aria-label": string;
|
|
46
|
+
onValueChange: (value: TValue) => void;
|
|
47
|
+
tabs: Array<{
|
|
48
|
+
label: ReactNode;
|
|
49
|
+
value: TValue;
|
|
50
|
+
}>;
|
|
51
|
+
value: TValue;
|
|
52
|
+
}
|
|
53
|
+
export declare function Tabs<TValue extends string>({ "aria-label": ariaLabel, onValueChange, tabs, value, }: TabsProps<TValue>): import("react").JSX.Element;
|
|
54
|
+
export interface ProgressStepsProps {
|
|
55
|
+
current: number;
|
|
56
|
+
steps: string[];
|
|
57
|
+
}
|
|
58
|
+
export declare function ProgressSteps({ current, steps }: ProgressStepsProps): import("react").JSX.Element;
|
|
59
|
+
export interface ModalProps {
|
|
60
|
+
actions?: ReactNode;
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
onClose: () => void;
|
|
63
|
+
open: boolean;
|
|
64
|
+
title: ReactNode;
|
|
65
|
+
}
|
|
66
|
+
export declare function Modal({ actions, children, onClose, open, title }: ModalProps): import("react").JSX.Element | null;
|
|
67
|
+
//# sourceMappingURL=components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../src/components.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
|
package/dist/morass.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("react/jsx-runtime");function t(...e){return e.filter(Boolean).join(` `)}function n(e,t){return`${e} ${e}--${t}`}function r({children:n,className:r,icon:i,type:a=`button`,variant:o=`secondary`,...s}){return(0,e.jsxs)(`button`,{className:t(`m-button`,`m-button--${o}`,r),type:a,...s,children:[i?(0,e.jsx)(`span`,{className:`m-button__icon`,children:i}):null,n?(0,e.jsx)(`span`,{className:`m-button__label`,children:n}):null]})}function i({actions:n,children:r,className:i,eyebrow:a,title:o,...s}){return(0,e.jsxs)(`section`,{className:t(`m-card`,i),...s,children:[a||o||n?(0,e.jsxs)(`header`,{className:`m-card__header`,children:[(0,e.jsxs)(`div`,{children:[a?(0,e.jsx)(`p`,{className:`m-eyebrow`,children:a}):null,o?(0,e.jsx)(`h2`,{className:`m-card__title`,children:o}):null]}),n?(0,e.jsx)(`div`,{className:`m-card__actions`,children:n}):null]}):null,r?(0,e.jsx)(`div`,{className:`m-card__body`,children:r}):null]})}function a({children:t,header:n,nav:r,sidebar:i}){return(0,e.jsxs)(`div`,{className:`m-app-frame`,children:[i?(0,e.jsx)(`aside`,{className:`m-app-frame__sidebar`,children:i}):null,(0,e.jsxs)(`div`,{className:`m-app-frame__main`,children:[n?(0,e.jsx)(`header`,{className:`m-app-frame__header`,children:n}):null,(0,e.jsx)(`main`,{className:`m-app-frame__content`,children:t}),r?(0,e.jsx)(`nav`,{className:`m-app-frame__nav`,children:r}):null]})]})}function o({error:t,helpText:n,label:r,labelProps:i,...a}){return(0,e.jsxs)(`label`,{className:`m-field`,...i,children:[(0,e.jsx)(`span`,{className:`m-field__label`,children:r}),(0,e.jsx)(`input`,{className:`m-input`,...a}),n?(0,e.jsx)(`span`,{className:`m-field__help`,children:n}):null,t?(0,e.jsx)(`span`,{className:`m-field__error`,children:t}):null]})}function s({children:t,error:n,helpText:r,label:i,labelProps:a,...o}){return(0,e.jsxs)(`label`,{className:`m-field`,...a,children:[(0,e.jsx)(`span`,{className:`m-field__label`,children:i}),(0,e.jsx)(`select`,{className:`m-input m-input--select`,...o,children:t}),r?(0,e.jsx)(`span`,{className:`m-field__help`,children:r}):null,n?(0,e.jsx)(`span`,{className:`m-field__error`,children:n}):null]})}function c({children:t,tone:r=`neutral`}){return(0,e.jsx)(`span`,{className:n(`m-status-pill`,r),children:t})}function l({label:t,value:n}){return(0,e.jsxs)(`div`,{className:`m-metric`,children:[(0,e.jsx)(`dt`,{children:t}),(0,e.jsx)(`dd`,{children:n})]})}function u({"aria-label":n,onValueChange:r,tabs:i,value:a}){return(0,e.jsx)(`div`,{"aria-label":n,className:`m-tabs`,role:`tablist`,children:i.map(n=>(0,e.jsx)(`button`,{"aria-selected":n.value===a,className:t(`m-tabs__tab`,n.value===a&&`m-tabs__tab--active`),onClick:()=>r(n.value),role:`tab`,type:`button`,children:n.label},n.value))})}function d({current:n,steps:r}){return(0,e.jsx)(`ol`,{className:`m-progress`,"aria-label":`Progress`,children:r.map((r,i)=>(0,e.jsxs)(`li`,{"aria-current":i===n?`step`:void 0,className:t(`m-progress__step`,i<=n&&`m-progress__step--active`),children:[(0,e.jsx)(`span`,{children:i+1}),(0,e.jsx)(`strong`,{children:r})]},r))})}function f({actions:t,children:n,onClose:i,open:a,title:o}){return a?(0,e.jsxs)(`div`,{className:`m-modal`,role:`presentation`,children:[(0,e.jsx)(`div`,{className:`m-modal__backdrop`,onClick:i}),(0,e.jsxs)(`section`,{"aria-modal":`true`,className:`m-modal__panel`,role:`dialog`,children:[(0,e.jsxs)(`header`,{className:`m-modal__header`,children:[(0,e.jsx)(`h2`,{children:o}),(0,e.jsx)(r,{"aria-label":`Close modal`,onClick:i,variant:`ghost`,children:`Close`})]}),(0,e.jsx)(`div`,{className:`m-modal__body`,children:n}),t?(0,e.jsx)(`footer`,{className:`m-modal__actions`,children:t}):null]})]}):null}exports.AppFrame=a,exports.Button=r,exports.Card=i,exports.Metric=l,exports.Modal=f,exports.ProgressSteps=d,exports.SelectField=s,exports.StatusPill=c,exports.Tabs=u,exports.TextField=o,exports.cx=t,exports.toneClass=n;
|
package/dist/morass.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { jsx as e, jsxs as t } from "react/jsx-runtime";
|
|
2
|
+
//#region src/utils.ts
|
|
3
|
+
function n(...e) {
|
|
4
|
+
return e.filter(Boolean).join(" ");
|
|
5
|
+
}
|
|
6
|
+
function r(e, t) {
|
|
7
|
+
return `${e} ${e}--${t}`;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/components.tsx
|
|
11
|
+
function i({ children: r, className: i, icon: a, type: o = "button", variant: s = "secondary", ...c }) {
|
|
12
|
+
return /* @__PURE__ */ t("button", {
|
|
13
|
+
className: n("m-button", `m-button--${s}`, i),
|
|
14
|
+
type: o,
|
|
15
|
+
...c,
|
|
16
|
+
children: [a ? /* @__PURE__ */ e("span", {
|
|
17
|
+
className: "m-button__icon",
|
|
18
|
+
children: a
|
|
19
|
+
}) : null, r ? /* @__PURE__ */ e("span", {
|
|
20
|
+
className: "m-button__label",
|
|
21
|
+
children: r
|
|
22
|
+
}) : null]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function a({ actions: r, children: i, className: a, eyebrow: o, title: s, ...c }) {
|
|
26
|
+
return /* @__PURE__ */ t("section", {
|
|
27
|
+
className: n("m-card", a),
|
|
28
|
+
...c,
|
|
29
|
+
children: [o || s || r ? /* @__PURE__ */ t("header", {
|
|
30
|
+
className: "m-card__header",
|
|
31
|
+
children: [/* @__PURE__ */ t("div", { children: [o ? /* @__PURE__ */ e("p", {
|
|
32
|
+
className: "m-eyebrow",
|
|
33
|
+
children: o
|
|
34
|
+
}) : null, s ? /* @__PURE__ */ e("h2", {
|
|
35
|
+
className: "m-card__title",
|
|
36
|
+
children: s
|
|
37
|
+
}) : null] }), r ? /* @__PURE__ */ e("div", {
|
|
38
|
+
className: "m-card__actions",
|
|
39
|
+
children: r
|
|
40
|
+
}) : null]
|
|
41
|
+
}) : null, i ? /* @__PURE__ */ e("div", {
|
|
42
|
+
className: "m-card__body",
|
|
43
|
+
children: i
|
|
44
|
+
}) : null]
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function o({ children: n, header: r, nav: i, sidebar: a }) {
|
|
48
|
+
return /* @__PURE__ */ t("div", {
|
|
49
|
+
className: "m-app-frame",
|
|
50
|
+
children: [a ? /* @__PURE__ */ e("aside", {
|
|
51
|
+
className: "m-app-frame__sidebar",
|
|
52
|
+
children: a
|
|
53
|
+
}) : null, /* @__PURE__ */ t("div", {
|
|
54
|
+
className: "m-app-frame__main",
|
|
55
|
+
children: [
|
|
56
|
+
r ? /* @__PURE__ */ e("header", {
|
|
57
|
+
className: "m-app-frame__header",
|
|
58
|
+
children: r
|
|
59
|
+
}) : null,
|
|
60
|
+
/* @__PURE__ */ e("main", {
|
|
61
|
+
className: "m-app-frame__content",
|
|
62
|
+
children: n
|
|
63
|
+
}),
|
|
64
|
+
i ? /* @__PURE__ */ e("nav", {
|
|
65
|
+
className: "m-app-frame__nav",
|
|
66
|
+
children: i
|
|
67
|
+
}) : null
|
|
68
|
+
]
|
|
69
|
+
})]
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function s({ error: n, helpText: r, label: i, labelProps: a, ...o }) {
|
|
73
|
+
return /* @__PURE__ */ t("label", {
|
|
74
|
+
className: "m-field",
|
|
75
|
+
...a,
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ e("span", {
|
|
78
|
+
className: "m-field__label",
|
|
79
|
+
children: i
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ e("input", {
|
|
82
|
+
className: "m-input",
|
|
83
|
+
...o
|
|
84
|
+
}),
|
|
85
|
+
r ? /* @__PURE__ */ e("span", {
|
|
86
|
+
className: "m-field__help",
|
|
87
|
+
children: r
|
|
88
|
+
}) : null,
|
|
89
|
+
n ? /* @__PURE__ */ e("span", {
|
|
90
|
+
className: "m-field__error",
|
|
91
|
+
children: n
|
|
92
|
+
}) : null
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function c({ children: n, error: r, helpText: i, label: a, labelProps: o, ...s }) {
|
|
97
|
+
return /* @__PURE__ */ t("label", {
|
|
98
|
+
className: "m-field",
|
|
99
|
+
...o,
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ e("span", {
|
|
102
|
+
className: "m-field__label",
|
|
103
|
+
children: a
|
|
104
|
+
}),
|
|
105
|
+
/* @__PURE__ */ e("select", {
|
|
106
|
+
className: "m-input m-input--select",
|
|
107
|
+
...s,
|
|
108
|
+
children: n
|
|
109
|
+
}),
|
|
110
|
+
i ? /* @__PURE__ */ e("span", {
|
|
111
|
+
className: "m-field__help",
|
|
112
|
+
children: i
|
|
113
|
+
}) : null,
|
|
114
|
+
r ? /* @__PURE__ */ e("span", {
|
|
115
|
+
className: "m-field__error",
|
|
116
|
+
children: r
|
|
117
|
+
}) : null
|
|
118
|
+
]
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function l({ children: t, tone: n = "neutral" }) {
|
|
122
|
+
return /* @__PURE__ */ e("span", {
|
|
123
|
+
className: r("m-status-pill", n),
|
|
124
|
+
children: t
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function u({ label: n, value: r }) {
|
|
128
|
+
return /* @__PURE__ */ t("div", {
|
|
129
|
+
className: "m-metric",
|
|
130
|
+
children: [/* @__PURE__ */ e("dt", { children: n }), /* @__PURE__ */ e("dd", { children: r })]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function d({ "aria-label": t, onValueChange: r, tabs: i, value: a }) {
|
|
134
|
+
return /* @__PURE__ */ e("div", {
|
|
135
|
+
"aria-label": t,
|
|
136
|
+
className: "m-tabs",
|
|
137
|
+
role: "tablist",
|
|
138
|
+
children: i.map((t) => /* @__PURE__ */ e("button", {
|
|
139
|
+
"aria-selected": t.value === a,
|
|
140
|
+
className: n("m-tabs__tab", t.value === a && "m-tabs__tab--active"),
|
|
141
|
+
onClick: () => r(t.value),
|
|
142
|
+
role: "tab",
|
|
143
|
+
type: "button",
|
|
144
|
+
children: t.label
|
|
145
|
+
}, t.value))
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function f({ current: r, steps: i }) {
|
|
149
|
+
return /* @__PURE__ */ e("ol", {
|
|
150
|
+
className: "m-progress",
|
|
151
|
+
"aria-label": "Progress",
|
|
152
|
+
children: i.map((i, a) => /* @__PURE__ */ t("li", {
|
|
153
|
+
"aria-current": a === r ? "step" : void 0,
|
|
154
|
+
className: n("m-progress__step", a <= r && "m-progress__step--active"),
|
|
155
|
+
children: [/* @__PURE__ */ e("span", { children: a + 1 }), /* @__PURE__ */ e("strong", { children: i })]
|
|
156
|
+
}, i))
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function p({ actions: n, children: r, onClose: a, open: o, title: s }) {
|
|
160
|
+
return o ? /* @__PURE__ */ t("div", {
|
|
161
|
+
className: "m-modal",
|
|
162
|
+
role: "presentation",
|
|
163
|
+
children: [/* @__PURE__ */ e("div", {
|
|
164
|
+
className: "m-modal__backdrop",
|
|
165
|
+
onClick: a
|
|
166
|
+
}), /* @__PURE__ */ t("section", {
|
|
167
|
+
"aria-modal": "true",
|
|
168
|
+
className: "m-modal__panel",
|
|
169
|
+
role: "dialog",
|
|
170
|
+
children: [
|
|
171
|
+
/* @__PURE__ */ t("header", {
|
|
172
|
+
className: "m-modal__header",
|
|
173
|
+
children: [/* @__PURE__ */ e("h2", { children: s }), /* @__PURE__ */ e(i, {
|
|
174
|
+
"aria-label": "Close modal",
|
|
175
|
+
onClick: a,
|
|
176
|
+
variant: "ghost",
|
|
177
|
+
children: "Close"
|
|
178
|
+
})]
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ e("div", {
|
|
181
|
+
className: "m-modal__body",
|
|
182
|
+
children: r
|
|
183
|
+
}),
|
|
184
|
+
n ? /* @__PURE__ */ e("footer", {
|
|
185
|
+
className: "m-modal__actions",
|
|
186
|
+
children: n
|
|
187
|
+
}) : null
|
|
188
|
+
]
|
|
189
|
+
})]
|
|
190
|
+
}) : null;
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
export { o as AppFrame, i as Button, a as Card, u as Metric, p as Modal, f as ProgressSteps, c as SelectField, l as StatusPill, d as Tabs, s as TextField, n as cx, r as toneClass };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){switch(e){case`overdue`:return`danger`;case`due-soon`:return`warning`;case`done`:return`success`;case`on-track`:return`info`}}function t(e){if(e<0){let t=Math.abs(e);return`${t} day${t===1?``:`s`} overdue`}return e===0?`Due today`:e===1?`Due tomorrow`:`Due in ${e} days`}exports.formatRelativeDue=t,exports.getDueStateTone=e;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Tone } from "./utils";
|
|
2
|
+
export type DueState = "overdue" | "due-soon" | "on-track" | "done";
|
|
3
|
+
export declare function getDueStateTone(state: DueState): Tone;
|
|
4
|
+
export declare function formatRelativeDue(daysUntilDue: number): string;
|
|
5
|
+
//# sourceMappingURL=reminders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reminders.d.ts","sourceRoot":"","sources":["../src/reminders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAEpE,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAWrD;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAe9D"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/reminders.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
switch (e) {
|
|
4
|
+
case "overdue": return "danger";
|
|
5
|
+
case "due-soon": return "warning";
|
|
6
|
+
case "done": return "success";
|
|
7
|
+
case "on-track": return "info";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function t(e) {
|
|
11
|
+
if (e < 0) {
|
|
12
|
+
let t = Math.abs(e);
|
|
13
|
+
return `${t} day${t === 1 ? "" : "s"} overdue`;
|
|
14
|
+
}
|
|
15
|
+
return e === 0 ? "Due today" : e === 1 ? "Due tomorrow" : `Due in ${e} days`;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { t as formatRelativeDue, e as getDueStateTone };
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
:root{--m-color-bg:#f7f4ef;--m-color-surface:#fff;--m-color-surface-muted:#f0f7f4;--m-color-text:#1d2524;--m-color-text-muted:#5f6d6a;--m-color-border:#d9ded8;--m-color-primary:#1d766f;--m-color-primary-strong:#115c56;--m-color-danger:#b42318;--m-color-danger-bg:#fef3f2;--m-color-warning:#b45309;--m-color-warning-bg:#fff7ed;--m-color-success:#047857;--m-color-success-bg:#ecfdf3;--m-color-info:#1d4ed8;--m-color-info-bg:#eff6ff;--m-radius:8px;--m-shadow:0 16px 40px #1d252414;--m-font:Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif}*{box-sizing:border-box}body{background:var(--m-color-bg);color:var(--m-color-text);font-family:var(--m-font);margin:0}.m-app-frame{grid-template-columns:248px minmax(0,1fr);min-height:100vh;display:grid}.m-app-frame__sidebar{color:#f8faf8;background:#143330;min-height:100vh;padding:20px 16px}.m-app-frame__main{grid-template-rows:auto minmax(0,1fr) auto;min-width:0;display:grid}.m-app-frame__header{border-bottom:1px solid var(--m-color-border);z-index:5;background:#ffffffeb;align-items:center;gap:16px;min-height:64px;padding:12px 24px;display:flex;position:sticky;top:0}.m-app-frame__content{min-width:0;padding:24px}.m-app-frame__nav{background:var(--m-color-surface);border-top:1px solid var(--m-color-border);gap:8px;padding:8px;display:none}.m-button{border-radius:var(--m-radius);cursor:pointer;font:inherit;border:1px solid #0000;justify-content:center;align-items:center;gap:8px;min-height:40px;padding:8px 14px;font-weight:700;transition:background .12s,border-color .12s,color .12s;display:inline-flex}.m-button:disabled{cursor:not-allowed;opacity:.55}.m-button--primary{background:var(--m-color-primary);color:#fff}.m-button--primary:hover{background:var(--m-color-primary-strong)}.m-button--secondary{background:var(--m-color-surface);border-color:var(--m-color-border);color:var(--m-color-text)}.m-button--secondary:hover,.m-button--ghost:hover{background:var(--m-color-surface-muted)}.m-button--ghost{color:inherit;background:0 0}.m-button--danger{background:var(--m-color-danger);color:#fff}.m-button__icon{align-items:center;display:inline-flex}.m-card{background:var(--m-color-surface);border:1px solid var(--m-color-border);border-radius:var(--m-radius);box-shadow:var(--m-shadow);min-width:0}.m-card__header{border-bottom:1px solid var(--m-color-border);justify-content:space-between;align-items:flex-start;gap:16px;padding:16px 18px;display:flex}.m-card__title{margin:0;font-size:1rem;line-height:1.3}.m-card__actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.m-card__body{padding:16px 18px}.m-eyebrow{color:var(--m-color-text-muted);letter-spacing:0;text-transform:uppercase;margin:0 0 4px;font-size:.76rem;font-weight:800}.m-field{gap:6px;display:grid}.m-field__label{color:var(--m-color-text);font-size:.86rem;font-weight:700}.m-field__help,.m-field__error{font-size:.78rem}.m-field__help{color:var(--m-color-text-muted)}.m-field__error{color:var(--m-color-danger)}.m-input{border:1px solid var(--m-color-border);border-radius:var(--m-radius);color:var(--m-color-text);font:inherit;background:#fff;width:100%;min-height:42px;padding:9px 11px}.m-input:focus,.m-button:focus-visible,.m-tabs__tab:focus-visible{outline-offset:2px;outline:3px solid #1d766f40}.m-status-pill{border-radius:999px;align-items:center;min-height:24px;padding:3px 9px;font-size:.78rem;font-weight:800;display:inline-flex}.m-status-pill--neutral{color:#384642;background:#eef1ef}.m-status-pill--info{background:var(--m-color-info-bg);color:var(--m-color-info)}.m-status-pill--success{background:var(--m-color-success-bg);color:var(--m-color-success)}.m-status-pill--warning{background:var(--m-color-warning-bg);color:var(--m-color-warning)}.m-status-pill--danger{background:var(--m-color-danger-bg);color:var(--m-color-danger)}.m-metric{gap:3px;display:grid}.m-metric dt{color:var(--m-color-text-muted);margin:0;font-size:.78rem;font-weight:700}.m-metric dd{margin:0;font-size:1.35rem;font-weight:800}.m-tabs{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.m-tabs__tab{color:var(--m-color-text-muted);cursor:pointer;font:inherit;background:0 0;border:1px solid #0000;border-radius:999px;min-height:34px;padding:6px 13px;font-size:.86rem;font-weight:800}.m-tabs__tab--active{background:var(--m-color-text);color:#fff}.m-progress{gap:10px;margin:0;padding:0;list-style:none;display:grid}.m-progress__step{color:var(--m-color-text-muted);grid-template-columns:28px minmax(0,1fr);align-items:center;gap:10px;display:grid}.m-progress__step span{background:#e6e9e6;border-radius:50%;justify-content:center;align-items:center;width:28px;height:28px;font-weight:800;display:inline-flex}.m-progress__step--active{color:var(--m-color-text)}.m-progress__step--active span{background:var(--m-color-primary);color:#fff}.m-modal{z-index:20;position:fixed;inset:0}.m-modal__backdrop{background:#0f172a70;position:absolute;inset:0}.m-modal__panel{background:var(--m-color-surface);border-radius:var(--m-radius);width:100%;max-width:min(620px,100vw - 32px);max-height:min(720px,100vh - 32px);position:absolute;top:50%;left:50%;overflow:auto;transform:translate(-50%,-50%);box-shadow:0 24px 80px #0f172a3d}.m-modal__header,.m-modal__actions{justify-content:space-between;align-items:center;gap:12px;padding:16px 18px;display:flex}.m-modal__header{border-bottom:1px solid var(--m-color-border)}.m-modal__header h2{margin:0;font-size:1.1rem}.m-modal__body{gap:14px;padding:18px;display:grid}.m-modal__actions{border-top:1px solid var(--m-color-border);justify-content:flex-end}@media (width<=820px){.m-app-frame{grid-template-columns:1fr}.m-app-frame__sidebar{display:none}.m-app-frame__content{padding:16px}.m-app-frame__nav{justify-content:space-around;display:flex;position:sticky;bottom:0}}
|
|
2
|
+
/*$vite$:1*/
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function cx(...values: Array<string | false | null | undefined>): string;
|
|
2
|
+
export type Tone = "neutral" | "info" | "success" | "warning" | "danger";
|
|
3
|
+
export declare function toneClass(prefix: string, tone: Tone): string;
|
|
4
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,EAAE,CAChB,GAAG,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC,GAClD,MAAM,CAER;AAED,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEzE,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5D"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@effigy-analytics/morass",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Composable React UI primitives for durable product interfaces.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Effigy Analytics",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/effigy-analytics/morass.git"
|
|
11
|
+
},
|
|
12
|
+
"sideEffects": [
|
|
13
|
+
"**/*.css"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/morass.cjs",
|
|
16
|
+
"module": "./dist/morass.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/morass.js",
|
|
26
|
+
"require": "./dist/morass.cjs"
|
|
27
|
+
},
|
|
28
|
+
"./reminders": {
|
|
29
|
+
"types": "./dist/reminders.d.ts",
|
|
30
|
+
"import": "./dist/reminders.js",
|
|
31
|
+
"require": "./dist/reminders.cjs"
|
|
32
|
+
},
|
|
33
|
+
"./styles.css": "./dist/styles.css"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "vite build && tsc -p tsconfig.build.json",
|
|
37
|
+
"check": "npm run format:check && npm run lint && npm run typecheck && npm run test && npm run build && npm run pack:check",
|
|
38
|
+
"dev": "vite --host 0.0.0.0",
|
|
39
|
+
"format": "prettier --write .",
|
|
40
|
+
"format:check": "prettier --check .",
|
|
41
|
+
"lint": "eslint .",
|
|
42
|
+
"pack:check": "npm_config_cache=${TMPDIR:-/tmp}/morass-npm-cache npm pack --dry-run",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
48
|
+
"react-dom": "^18.2.0 || ^19.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@eslint/js": "^10.0.1",
|
|
52
|
+
"@types/node": "^26.1.0",
|
|
53
|
+
"@types/react": "^19.1.8",
|
|
54
|
+
"@types/react-dom": "^19.1.6",
|
|
55
|
+
"@vitejs/plugin-react": "^6.0.3",
|
|
56
|
+
"eslint": "^10.6.0",
|
|
57
|
+
"globals": "^17.7.0",
|
|
58
|
+
"prettier": "^3.9.4",
|
|
59
|
+
"typescript": "^6.0.3",
|
|
60
|
+
"typescript-eslint": "^8.62.1",
|
|
61
|
+
"vite": "^8.1.1",
|
|
62
|
+
"vitest": "^4.1.10"
|
|
63
|
+
}
|
|
64
|
+
}
|