@atelic-action/ui 0.17.2 → 1.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 +432 -45
- package/bin/atelic-check-base-path.ts +5 -0
- package/bin/atelic-clean-sitemap.ts +5 -0
- package/bin/atelic-contact-canary.ts +5 -0
- package/bin/atelic-print-sheets.sh +1 -1
- package/bin/atelic-seal-document.mjs +1 -1
- package/bin/atelic-serve-static.ts +1 -1
- package/dist/gate/index.d.ts +1 -1
- package/dist/gate/index.js +1 -1
- package/dist/gate/middleware.d.ts +4 -1
- package/dist/gate/middleware.js +14 -5
- package/dist/gate/wall.d.ts +25 -0
- package/dist/gate/wall.js +41 -2
- package/dist/routing/basePath.d.ts +24 -0
- package/dist/routing/basePath.js +54 -0
- package/dist/vite/index.d.ts +3 -2
- package/dist/vite/index.js +3 -2
- package/dist/vite/marketing-config.d.ts +50 -0
- package/dist/vite/marketing-config.js +83 -0
- package/package.json +164 -5
- package/src/app/AppProvider.tsx +41 -0
- package/src/app/AuthGuard.tsx +27 -0
- package/src/app/CardErrorBoundary.tsx +39 -0
- package/src/app/ErrorFallback.tsx +39 -0
- package/src/app/GoogleGlyph.tsx +22 -0
- package/src/app/config.ts +54 -0
- package/src/app/configure.ts +18 -0
- package/src/app/context/AppContext.tsx +52 -0
- package/src/app/context/SidebarContext.tsx +124 -0
- package/src/app/context/UserContext.tsx +139 -0
- package/src/app/hooks/useDebounce.ts +12 -0
- package/src/app/hooks/useIsDesktop.ts +31 -0
- package/src/app/hooks/useWakeLock.ts +49 -0
- package/src/app/index.ts +64 -0
- package/src/app/layout/ActionButton.tsx +67 -0
- package/src/app/layout/AppLayout.tsx +110 -0
- package/src/app/layout/AppPage.tsx +268 -0
- package/src/app/layout/Breadcrumbs.tsx +57 -0
- package/src/app/layout/DesktopRail.tsx +168 -0
- package/src/app/layout/FormActionButtons.tsx +69 -0
- package/src/app/layout/MobileMenu.tsx +156 -0
- package/src/app/layout/MobileTabBar.tsx +43 -0
- package/src/app/layout/PageError.tsx +30 -0
- package/src/app/layout/PageSkeleton.tsx +65 -0
- package/src/app/layout/SectionCards.tsx +33 -0
- package/src/app/layout/UserMenu.tsx +104 -0
- package/src/app/layout/identity.ts +22 -0
- package/src/app/layout/index.ts +20 -0
- package/src/app/layout/nav.ts +52 -0
- package/src/app/lib/dates.ts +57 -0
- package/src/app/lib/env.ts +37 -0
- package/src/app/lib/format.ts +61 -0
- package/src/app/lib/http.ts +205 -0
- package/src/app/lib/lastAuth.ts +45 -0
- package/src/app/lib/oauth.ts +32 -0
- package/src/app/lib/publicRoutes.ts +33 -0
- package/src/app/lib/queryClient.ts +38 -0
- package/src/app/lib/search.ts +17 -0
- package/src/app/lib/session.ts +36 -0
- package/src/app/lib/tokenRefresh.ts +137 -0
- package/src/app/lib/transformKeys.ts +60 -0
- package/src/app/lib/units.ts +228 -0
- package/src/app/lib/unwrap.ts +48 -0
- package/src/app/lib/utils.ts +10 -0
- package/src/app/stores/authStore.ts +80 -0
- package/src/app/stores/storage.ts +40 -0
- package/src/app/stores/unitsStore.ts +54 -0
- package/src/app/types/index.ts +72 -0
- package/src/app/types/query.ts +11 -0
- package/src/app/ui/accordion.tsx +54 -0
- package/src/app/ui/alert-dialog.tsx +114 -0
- package/src/app/ui/alert.tsx +49 -0
- package/src/app/ui/avatar.tsx +45 -0
- package/src/app/ui/badge-list.tsx +51 -0
- package/src/app/ui/badge.tsx +33 -0
- package/src/app/ui/button.tsx +49 -0
- package/src/app/ui/callout.tsx +22 -0
- package/src/app/ui/card.tsx +55 -0
- package/src/app/ui/checkbox.tsx +26 -0
- package/src/app/ui/clear-button.tsx +42 -0
- package/src/app/ui/command.tsx +140 -0
- package/src/app/ui/country-dropdown.tsx +184 -0
- package/src/app/ui/dialog.tsx +104 -0
- package/src/app/ui/dropdown-menu.tsx +185 -0
- package/src/app/ui/form.tsx +172 -0
- package/src/app/ui/index.ts +36 -0
- package/src/app/ui/input.tsx +22 -0
- package/src/app/ui/label.tsx +19 -0
- package/src/app/ui/option-select.tsx +56 -0
- package/src/app/ui/pagination.tsx +90 -0
- package/src/app/ui/popover.tsx +29 -0
- package/src/app/ui/progress.tsx +25 -0
- package/src/app/ui/search-input.tsx +63 -0
- package/src/app/ui/select.tsx +151 -0
- package/src/app/ui/separator.tsx +24 -0
- package/src/app/ui/sheet.tsx +119 -0
- package/src/app/ui/slider.tsx +23 -0
- package/src/app/ui/switch.tsx +27 -0
- package/src/app/ui/textarea.tsx +21 -0
- package/src/app/ui/tooltip.tsx +32 -0
- package/src/artifact/ArtifactShell.tsx +2 -2
- package/src/artifact/Gate.tsx +2 -2
- package/src/artifact/Note.tsx +9 -39
- package/src/artifact/Paragraph.tsx +65 -0
- package/src/artifact/Read.tsx +406 -0
- package/src/artifact/Writeup.tsx +7 -7
- package/src/artifact/index.ts +1 -0
- package/src/chrome/SiteShell.tsx +141 -0
- package/src/chrome/index.ts +2 -0
- package/src/components/Disclosure.tsx +80 -14
- package/src/components/GateLogin.tsx +1 -1
- package/src/components/Watermark.tsx +1 -1
- package/src/components/index.ts +6 -2
- package/src/gate/index.ts +1 -1
- package/src/gate/middleware.ts +17 -6
- package/src/gate/wall.ts +60 -2
- package/src/lib/basePathAudit.ts +96 -0
- package/src/lib/displayDate.ts +25 -0
- package/src/lib/honeypot.ts +11 -0
- package/src/lib/hours.ts +28 -0
- package/src/lib/sitemap.ts +34 -0
- package/src/lib/trackEvent.ts +26 -0
- package/src/lib/useOpenHeight.ts +28 -0
- package/src/primitives/Button.tsx +3 -1
- package/src/primitives/Chip.tsx +3 -1
- package/src/primitives/ImageFrame.tsx +48 -0
- package/src/primitives/ProseBlocks.tsx +67 -0
- package/src/primitives/QuoteCard.tsx +20 -0
- package/src/primitives/StarRow.tsx +37 -0
- package/src/primitives/TickList.tsx +24 -0
- package/src/primitives/index.ts +5 -0
- package/src/routing/BasePathProvider.tsx +47 -0
- package/src/routing/basePath.ts +57 -0
- package/src/routing/index.ts +8 -0
- package/src/scripts/check-base-path.ts +130 -0
- package/src/scripts/clean-sitemap.ts +27 -0
- package/src/scripts/contact-canary.ts +98 -0
- package/src/scripts/serve-static.ts +29 -3
- package/src/sections/BlogIndex.tsx +57 -0
- package/src/sections/BlogPost.tsx +65 -0
- package/src/sections/CTABanner.tsx +93 -0
- package/src/sections/CTASection.tsx +60 -0
- package/src/sections/ComparisonTable.tsx +114 -0
- package/src/sections/ContactForm.tsx +163 -0
- package/src/sections/ContactInfoCard.tsx +92 -0
- package/src/sections/CredentialList.tsx +28 -0
- package/src/sections/DeviceShowcase.tsx +39 -0
- package/src/sections/ExpandList.tsx +58 -0
- package/src/sections/FAQBrowser.tsx +283 -0
- package/src/sections/FeatureDetail.tsx +60 -0
- package/src/sections/FeatureGrid.tsx +83 -0
- package/src/sections/Gallery.tsx +84 -0
- package/src/sections/Hero.tsx +110 -0
- package/src/sections/HoursTable.tsx +23 -0
- package/src/sections/JumpRail.tsx +35 -0
- package/src/sections/LegalPage.tsx +43 -0
- package/src/sections/LocationSection.tsx +66 -0
- package/src/sections/Locations.tsx +71 -0
- package/src/sections/LogoMarquee.tsx +27 -0
- package/src/sections/MapEmbed.tsx +75 -0
- package/src/sections/MediaBand.tsx +20 -0
- package/src/sections/MenuList.tsx +44 -0
- package/src/sections/PageHero.tsx +25 -0
- package/src/sections/PressQuotes.tsx +51 -0
- package/src/sections/PricingBand.tsx +43 -0
- package/src/sections/PricingCard.tsx +36 -0
- package/src/sections/ProcessSteps.tsx +45 -0
- package/src/sections/ProfileCards.tsx +73 -0
- package/src/sections/RevealSlider.tsx +156 -0
- package/src/sections/ReviewCarousel.tsx +223 -0
- package/src/sections/ReviewWall.tsx +220 -0
- package/src/sections/SocialStrip.tsx +83 -0
- package/src/sections/SplitSection.tsx +56 -0
- package/src/sections/index.ts +76 -0
- package/src/sections/siteConfig.ts +201 -0
- package/src/styles/app.css +673 -0
- package/src/styles/artifact.css +759 -401
- package/src/styles/base.css +49 -47
- package/src/styles/chrome.css +71 -71
- package/src/styles/components.css +150 -140
- package/src/styles/gate.css +29 -29
- package/src/styles/primitives.css +190 -25
- package/src/styles/sections.css +2652 -0
- package/src/styles/star-rating.css +2 -2
- package/src/vite/index.ts +9 -2
- package/src/vite/marketing-config.ts +128 -0
- package/src/components/Collapsible.tsx +0 -43
- /package/src/scripts/{build-gate-payload.mjs → seal-document.mjs} +0 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract between a marketing site and the package's sections, moved
|
|
3
|
+
* here from template-marketing in 0.19.0 (ATE-643).
|
|
4
|
+
*
|
|
5
|
+
* SiteShell maps this config onto the chrome (header, menu, footer, sticky
|
|
6
|
+
* CTA bar), the sections that need the business's facts take it (or only the
|
|
7
|
+
* keys they read) as their `site` prop, and a site's structured data helpers
|
|
8
|
+
* render from it, so standing up a new site means writing one of these plus
|
|
9
|
+
* a theme.css, never touching the components themselves.
|
|
10
|
+
*/
|
|
11
|
+
import type { SiteLink, SocialLink } from "../types";
|
|
12
|
+
|
|
13
|
+
export type { SiteLink, SocialLink };
|
|
14
|
+
|
|
15
|
+
export interface NavItem {
|
|
16
|
+
label: string;
|
|
17
|
+
to: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CTA {
|
|
21
|
+
label: string;
|
|
22
|
+
href: string;
|
|
23
|
+
/** Opens in a new tab with rel="noopener" when true (e.g. a booking portal). */
|
|
24
|
+
external?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface OpeningHours {
|
|
28
|
+
/** Row label as displayed, e.g. "Monday" or "Friday to Sunday". */
|
|
29
|
+
label: string;
|
|
30
|
+
/** Compact label for the footer, e.g. "Mon" or "Fri to Sun". */
|
|
31
|
+
labelShort: string;
|
|
32
|
+
/** schema.org day names covered by this row (empty for closed spans). */
|
|
33
|
+
days: string[];
|
|
34
|
+
/** 24 hour "HH:MM"; omit both for a closed row. */
|
|
35
|
+
opens?: string;
|
|
36
|
+
closes?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Display text for a row without posted times, e.g. "By appointment".
|
|
39
|
+
* Renders wherever hours appear; defaults to "Closed". Rows without
|
|
40
|
+
* opens/closes never emit an openingHoursSpecification, so a
|
|
41
|
+
* by-appointment business states no invented hours in structured data.
|
|
42
|
+
*/
|
|
43
|
+
note?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface Address {
|
|
47
|
+
street: string;
|
|
48
|
+
locality: string;
|
|
49
|
+
region: string;
|
|
50
|
+
postalCode: string;
|
|
51
|
+
country: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface Founder {
|
|
55
|
+
name: string;
|
|
56
|
+
jobTitle: string;
|
|
57
|
+
honorificSuffix?: string;
|
|
58
|
+
alumniOf?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Copy for the access-gate login screen. Present in the config so the login
|
|
63
|
+
* page is themed and worded per client with no code edits. The gate itself is
|
|
64
|
+
* turned on by setting GATE_SESSION_SECRET on the Vercel project, not by this
|
|
65
|
+
* block (README.md, The Access Gate).
|
|
66
|
+
*/
|
|
67
|
+
export interface GateConfig {
|
|
68
|
+
/** Mono eyebrow above the headline, e.g. "Private preview". */
|
|
69
|
+
eyebrow?: string;
|
|
70
|
+
/** Login headline. */
|
|
71
|
+
headline: string;
|
|
72
|
+
/** Sub-lead under the headline. */
|
|
73
|
+
lead: string;
|
|
74
|
+
/** Fine-print attribution, e.g. "Built by Jane Maker". Defaults to `attribution`. */
|
|
75
|
+
builtBy?: string;
|
|
76
|
+
/** Contact email shown in the fine print. Defaults to `email`. */
|
|
77
|
+
contactEmail?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface SiteConfig {
|
|
81
|
+
/** Brand name as rendered in the wordmark and structured data. */
|
|
82
|
+
name: string;
|
|
83
|
+
/**
|
|
84
|
+
* Canonical URL, no trailing slash, e.g. "https://example.com". For a cut
|
|
85
|
+
* with a `basePath` it is the full URL including the prefix
|
|
86
|
+
* ("https://atwood.atelic.me/proto"), and the build fails if it does not
|
|
87
|
+
* end with the base.
|
|
88
|
+
*/
|
|
89
|
+
url: string;
|
|
90
|
+
/**
|
|
91
|
+
* The path prefix the site is served under, for a cut that does not own the
|
|
92
|
+
* root of its host: a site build previewed at "/proto" on the business's
|
|
93
|
+
* artifact host, which proxies those requests here. "" (the default) is the
|
|
94
|
+
* root. `marketingConfig` reads it for Vite's `base` and the router's
|
|
95
|
+
* `basepath`, and `SiteShell` hands it to `BasePathProvider`, which every
|
|
96
|
+
* link and image a section renders reads through `useBasePath`.
|
|
97
|
+
*/
|
|
98
|
+
basePath?: string;
|
|
99
|
+
/** Default meta description and LocalBusiness description. */
|
|
100
|
+
description: string;
|
|
101
|
+
/** schema.org business types, most general first, e.g. ["MedicalBusiness", "PhysicalTherapy"]. */
|
|
102
|
+
schemaType: string[];
|
|
103
|
+
/**
|
|
104
|
+
* The chrome identity. `src` is the mark image; omit it for a pure text
|
|
105
|
+
* wordmark. `tile` renders a CSS glyph tile instead of an image (a dark
|
|
106
|
+
* rounded square bearing the given character in the brand's own webfont,
|
|
107
|
+
* with the accent bar beneath — an SVG-as-img mark cannot load webfonts,
|
|
108
|
+
* so a lettered mark must be real DOM text to render true). `wordmark`
|
|
109
|
+
* overrides the rendered wordmark text when it should differ from `name`
|
|
110
|
+
* (e.g. a lowercase brand treatment); `run` appends the trailing fade bar
|
|
111
|
+
* after the wordmark (the Eyebrow's signature, worn by the brand itself).
|
|
112
|
+
*/
|
|
113
|
+
logo: { src?: string; alt: string; tile?: string; wordmark?: string; run?: boolean };
|
|
114
|
+
/** Google Fonts stylesheet URL for the theme's font stack. */
|
|
115
|
+
fontsHref?: string;
|
|
116
|
+
nav: NavItem[];
|
|
117
|
+
/** The site's primary conversion action; rendered in nav, sticky bar, and menus. */
|
|
118
|
+
cta: CTA;
|
|
119
|
+
/** Omit for businesses with no public phone; call surfaces render nothing. */
|
|
120
|
+
phone?: { e164: string; display: string };
|
|
121
|
+
email: string;
|
|
122
|
+
address: Address;
|
|
123
|
+
geo?: { latitude: number; longitude: number };
|
|
124
|
+
mapEmbedUrl?: string;
|
|
125
|
+
mapLinkUrl?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Path to a static map screenshot (e.g. "/images/map.jpg"). When set, the
|
|
128
|
+
* map renders as a lightweight image linking to directions instead of the
|
|
129
|
+
* click-to-load live embed — one request, no third-party chain, and it
|
|
130
|
+
* shows a real map on first paint.
|
|
131
|
+
*/
|
|
132
|
+
mapImage?: string;
|
|
133
|
+
hours: OpeningHours[];
|
|
134
|
+
/** Neighborhoods or cities served; feeds local SEO copy and structured data. */
|
|
135
|
+
serviceAreas: string[];
|
|
136
|
+
priceRange?: string;
|
|
137
|
+
/** Cuisine types for a Restaurant/FoodEstablishment (schema.org servesCuisine). */
|
|
138
|
+
servesCuisine?: string[];
|
|
139
|
+
founder?: Founder;
|
|
140
|
+
/** Names of offered services for structured data. */
|
|
141
|
+
offers?: string[];
|
|
142
|
+
/** Short brand paragraph for the footer. */
|
|
143
|
+
footerBlurb: string;
|
|
144
|
+
/** Extra footer nav links beyond the main nav (e.g. a patient portal). */
|
|
145
|
+
footerLinks?: SiteLink[];
|
|
146
|
+
/** Icon links (socials, the founder's own site) rendered in the footer brand column. */
|
|
147
|
+
socialLinks?: SocialLink[];
|
|
148
|
+
legalLinks?: SiteLink[];
|
|
149
|
+
/** Copyright attribution line suffix, e.g. "Dr. Alex Rivers, PT, DPT". */
|
|
150
|
+
attribution?: string;
|
|
151
|
+
/**
|
|
152
|
+
* Footer wording overrides: the heading over the address column (defaults
|
|
153
|
+
* to "Visit", which reads wrong for a practice with no storefront) and a
|
|
154
|
+
* short closing note beside the copyright line ("Made with love in ...").
|
|
155
|
+
*/
|
|
156
|
+
footer?: {
|
|
157
|
+
contactHeading?: string;
|
|
158
|
+
note?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Set false to drop the name and address lines from the contact column
|
|
161
|
+
* and leave only the phone and email under the heading (a practice with
|
|
162
|
+
* no storefront has nothing to visit). Defaults to true.
|
|
163
|
+
*/
|
|
164
|
+
showAddress?: boolean;
|
|
165
|
+
};
|
|
166
|
+
ogImage?: string;
|
|
167
|
+
/** Profile URLs for the schema.org sameAs entity graph (socials, listings). */
|
|
168
|
+
sameAs?: string[];
|
|
169
|
+
/**
|
|
170
|
+
* Robots meta override for every page (e.g. "noindex, nofollow" while the
|
|
171
|
+
* site lives on a preview subdomain). Defaults to indexable.
|
|
172
|
+
*/
|
|
173
|
+
robots?: string;
|
|
174
|
+
/**
|
|
175
|
+
* Analytics wiring. When `hubspotPortalId` is set, the HubSpot tracking code
|
|
176
|
+
* loads on every page and records visits; because each prospect gets a
|
|
177
|
+
* unique preview URL, a visit is attributable to that prospect. `hubspotRegion`
|
|
178
|
+
* picks the loader host and defaults to "na1"; na2 portals (loggable via a
|
|
179
|
+
* bcc.na2 address) load from js-na2.hs-scripts.com.
|
|
180
|
+
*
|
|
181
|
+
* `identify` ties a visit to a specific prospect: when the visit arrives with
|
|
182
|
+
* `?k=<token>` (the token embedded in that prospect's outreach link), the
|
|
183
|
+
* visitor is identified to HubSpot as `email`, so the visit attaches to that
|
|
184
|
+
* prospect's contact timeline. Visits without the token stay anonymous.
|
|
185
|
+
*/
|
|
186
|
+
analytics?: {
|
|
187
|
+
/**
|
|
188
|
+
* GA4 measurement id (e.g. "G-XXXXXXXXXX"). When set, the Google tag
|
|
189
|
+
* loads on every page and the conversion events in
|
|
190
|
+
* the site's own analytics module (the standard set in DEPLOY.md)
|
|
191
|
+
* reach GA. Independent of the HubSpot wiring; a site can carry either
|
|
192
|
+
* or both.
|
|
193
|
+
*/
|
|
194
|
+
googleTagId?: string;
|
|
195
|
+
hubspotPortalId?: string;
|
|
196
|
+
hubspotRegion?: "na1" | "na2" | "eu1";
|
|
197
|
+
identify?: { token: string; email: string };
|
|
198
|
+
};
|
|
199
|
+
/** Copy for the access-gate login screen (see GateConfig). */
|
|
200
|
+
gate?: GateConfig;
|
|
201
|
+
}
|