@ohhwells/bridge 0.1.83 → 0.1.84-next.249
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/dist/index.cjs +550 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +549 -128
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +141 -0
- package/dist/pages.cjs.map +1 -0
- package/dist/pages.d.cts +45 -0
- package/dist/pages.d.ts +45 -0
- package/dist/pages.js +107 -0
- package/dist/pages.js.map +1 -0
- package/dist/social-glyphs.cjs +1 -1
- package/dist/social-glyphs.cjs.map +1 -1
- package/dist/social-glyphs.js +1 -1
- package/dist/social-glyphs.js.map +1 -1
- package/dist/styles.css +58 -0
- package/package.json +8 -3
package/dist/pages.cjs
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/pages.ts
|
|
21
|
+
var pages_exports = {};
|
|
22
|
+
__export(pages_exports, {
|
|
23
|
+
DELETED_PAGE_PREFIX: () => DELETED_PAGE_PREFIX,
|
|
24
|
+
fetchSitePages: () => fetchSitePages,
|
|
25
|
+
renderCatchAllPage: () => renderCatchAllPage,
|
|
26
|
+
resolvePageRewrite: () => resolvePageRewrite,
|
|
27
|
+
resolveSitePage: () => resolveSitePage,
|
|
28
|
+
resolveSubdomain: () => resolveSubdomain,
|
|
29
|
+
sitePagesMiddleware: () => sitePagesMiddleware,
|
|
30
|
+
sitePagesMiddlewareConfig: () => sitePagesMiddlewareConfig
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(pages_exports);
|
|
33
|
+
|
|
34
|
+
// src/lib/site-pages.ts
|
|
35
|
+
var DELETED_PAGE_PREFIX = "/__ohw-deleted";
|
|
36
|
+
function resolveSubdomain(hostnameOverride) {
|
|
37
|
+
if (hostnameOverride) {
|
|
38
|
+
const parts = hostnameOverride.split(".");
|
|
39
|
+
if (parts.length >= 3 && parts[0] !== "www") return parts[0];
|
|
40
|
+
}
|
|
41
|
+
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL;
|
|
42
|
+
if (!siteUrl) return "";
|
|
43
|
+
try {
|
|
44
|
+
const parts = new URL(siteUrl).hostname.split(".");
|
|
45
|
+
if (parts.length >= 3 && parts[0] !== "www") return parts[0];
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
async function fetchSitePages(subdomainOverride) {
|
|
51
|
+
const subdomain = subdomainOverride || resolveSubdomain();
|
|
52
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL;
|
|
53
|
+
if (!subdomain || !apiUrl) return [];
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetch(`${apiUrl}/api/public/sites/${subdomain}/pages`, {
|
|
56
|
+
cache: "no-store"
|
|
57
|
+
});
|
|
58
|
+
if (!res.ok) return [];
|
|
59
|
+
const { pages } = await res.json();
|
|
60
|
+
return pages ?? [];
|
|
61
|
+
} catch {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function resolvePageRewrite(pathname, pages) {
|
|
66
|
+
const current = pages.find((page) => page.path === pathname);
|
|
67
|
+
if (current) {
|
|
68
|
+
if (current.is_deleted) return { path: `${DELETED_PAGE_PREFIX}${pathname}` };
|
|
69
|
+
if (current.is_physical && current.original_path && current.original_path !== current.path) {
|
|
70
|
+
return { path: current.original_path };
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const oldUrlOfRenamed = pages.find(
|
|
75
|
+
(page) => page.is_physical && page.original_path === pathname && page.path !== pathname
|
|
76
|
+
);
|
|
77
|
+
if (oldUrlOfRenamed) return { path: `${DELETED_PAGE_PREFIX}${pathname}` };
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
async function resolveSitePage(segments, subdomainOverride) {
|
|
81
|
+
if (`/${segments[0]}` === DELETED_PAGE_PREFIX) return { kind: "not-found" };
|
|
82
|
+
const path = `/${segments.join("/")}`;
|
|
83
|
+
const pages = await fetchSitePages(subdomainOverride);
|
|
84
|
+
const page = pages.find((entry) => entry.path === path && !entry.is_deleted);
|
|
85
|
+
if (!page) return { kind: "not-found" };
|
|
86
|
+
if (page.duplicated_from) {
|
|
87
|
+
const sourceSegment = page.duplicated_from === "/" ? "" : page.duplicated_from.replace(/^\//, "");
|
|
88
|
+
return { kind: "duplicate", sourceSegment, page };
|
|
89
|
+
}
|
|
90
|
+
return { kind: "blank", page };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/lib/site-pages-middleware.ts
|
|
94
|
+
var import_server = require("next/server");
|
|
95
|
+
async function sitePagesMiddleware(request) {
|
|
96
|
+
const { pathname } = request.nextUrl;
|
|
97
|
+
if (pathname.startsWith("/_next") || pathname.startsWith("/api") || /\.[a-zA-Z0-9]+$/.test(pathname)) {
|
|
98
|
+
return import_server.NextResponse.next();
|
|
99
|
+
}
|
|
100
|
+
const subdomain = request.nextUrl.searchParams.get("subdomain") || resolveSubdomain(request.nextUrl.hostname);
|
|
101
|
+
const pages = await fetchSitePages(subdomain || void 0);
|
|
102
|
+
if (pages.length === 0) return import_server.NextResponse.next();
|
|
103
|
+
const decision = resolvePageRewrite(pathname, pages);
|
|
104
|
+
if (!decision) return import_server.NextResponse.next();
|
|
105
|
+
return import_server.NextResponse.rewrite(new URL(decision.path, request.url));
|
|
106
|
+
}
|
|
107
|
+
var sitePagesMiddlewareConfig = {
|
|
108
|
+
matcher: ["/((?!_next|api).*)"]
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/lib/site-pages-render.ts
|
|
112
|
+
var import_headers = require("next/headers");
|
|
113
|
+
var import_navigation = require("next/navigation");
|
|
114
|
+
var import_react = require("react");
|
|
115
|
+
async function renderCatchAllPage(segments, subdomainOverride, handlers) {
|
|
116
|
+
const host = (await (0, import_headers.headers)()).get("host") ?? void 0;
|
|
117
|
+
const subdomain = subdomainOverride || resolveSubdomain(host) || void 0;
|
|
118
|
+
const result = await resolveSitePage(segments, subdomain);
|
|
119
|
+
if (result.kind === "not-found") (0, import_navigation.notFound)();
|
|
120
|
+
if (result.kind === "duplicate") {
|
|
121
|
+
try {
|
|
122
|
+
const sourceModule = await handlers.renderDuplicate(result.sourceSegment);
|
|
123
|
+
return (0, import_react.createElement)(sourceModule.default);
|
|
124
|
+
} catch {
|
|
125
|
+
(0, import_navigation.notFound)();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return handlers.renderBlank(result.page);
|
|
129
|
+
}
|
|
130
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
131
|
+
0 && (module.exports = {
|
|
132
|
+
DELETED_PAGE_PREFIX,
|
|
133
|
+
fetchSitePages,
|
|
134
|
+
renderCatchAllPage,
|
|
135
|
+
resolvePageRewrite,
|
|
136
|
+
resolveSitePage,
|
|
137
|
+
resolveSubdomain,
|
|
138
|
+
sitePagesMiddleware,
|
|
139
|
+
sitePagesMiddlewareConfig
|
|
140
|
+
});
|
|
141
|
+
//# sourceMappingURL=pages.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pages.ts","../src/lib/site-pages.ts","../src/lib/site-pages-middleware.ts","../src/lib/site-pages-render.ts"],"sourcesContent":["// Server-safe entry point (no 'use client' banner) — for middleware/Edge runtime and\n// Server Components. Keep this file free of React component exports; UI goes in the\n// default `@ohhwells/bridge` entry (src/index.ts).\nexport {\n DELETED_PAGE_PREFIX,\n resolveSubdomain,\n fetchSitePages,\n resolvePageRewrite,\n resolveSitePage,\n} from './lib/site-pages'\nexport type { SitePage, PageRewriteDecision, SitePageResolution } from './lib/site-pages'\nexport { sitePagesMiddleware, sitePagesMiddlewareConfig } from './lib/site-pages-middleware'\nexport { renderCatchAllPage } from './lib/site-pages-render'\nexport type { CatchAllPageHandlers } from './lib/site-pages-render'\n","// Shared page-CRUD infra (OHH-670): fetching a site's page list and deciding how the\n// catch-all route / middleware should handle deleted, renamed, and duplicated pages.\n// Server-safe (no React/browser APIs) so it can run in middleware (Edge runtime) and\n// Server Components — kept out of the main client-bundled entry point, see `../pages.ts`.\n\n// Prefix used to route deleted-physical-page requests into the catch-all `[...page]`\n// route, which has no file of its own at that segment and calls notFound() for it.\nexport const DELETED_PAGE_PREFIX = '/__ohw-deleted'\n\nexport type SitePage = {\n id: string\n path: string\n title: string\n is_physical: boolean\n original_path: string | null\n duplicated_from: string | null\n is_deleted: boolean\n}\n\n// Mirrors OhhwellsBridge's client-side resolveSubdomain: prefer the real request hostname\n// (window.location isn't available on the server, so callers pass the Host header/nextUrl\n// hostname instead) and only fall back to the NEXT_PUBLIC_SITE_URL env var when no hostname\n// is known — the only case that's true in local dev, where the host is just localhost.\nexport function resolveSubdomain(hostnameOverride?: string): string {\n if (hostnameOverride) {\n const parts = hostnameOverride.split('.')\n if (parts.length >= 3 && parts[0] !== 'www') return parts[0]\n }\n\n const siteUrl = process.env.NEXT_PUBLIC_SITE_URL\n if (!siteUrl) return ''\n try {\n const parts = new URL(siteUrl).hostname.split('.')\n if (parts.length >= 3 && parts[0] !== 'www') return parts[0]\n } catch {\n // ignore malformed env value\n }\n return ''\n}\n\n// `subdomainOverride` is the `?subdomain=` query param the canvas editor's iframe appends\n// (see `editUrl` in fo-class-experience). It's required locally: NEXT_PUBLIC_SITE_URL is\n// `http://localhost:3000` in dev, which resolveSubdomain() can't parse a subdomain from.\nexport async function fetchSitePages(subdomainOverride?: string): Promise<SitePage[]> {\n const subdomain = subdomainOverride || resolveSubdomain()\n const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL\n if (!subdomain || !apiUrl) return []\n\n try {\n // no-store, not a timed revalidate: middleware uses this list to decide whether a\n // path is deleted/renamed, and `next start`'s persistent Data Cache would otherwise\n // keep routing a just-deleted page's URL to its live content for longer than expected.\n const res = await fetch(`${apiUrl}/api/public/sites/${subdomain}/pages`, {\n cache: 'no-store',\n })\n if (!res.ok) return []\n const { pages } = (await res.json()) as { pages?: SitePage[] }\n\n // A reply without a list is not a list of none — the endpoint answers 200 with an empty body\n // when its own lookup failed. Handing that straight back put `undefined` into middleware and\n // took the whole site down with a 500 on every request.\n return pages ?? []\n } catch {\n return []\n }\n}\n\nexport type PageRewriteDecision = { path: string } | null\n\n// Middleware decision logic: given the current pathname and the site's page list, decide\n// whether to rewrite to the deleted-page placeholder or to a renamed physical page's real\n// file location. Callers still own the `_next`/`api`/static-file early-return and the actual\n// `NextResponse.rewrite` call, since those are Next.js-specific.\nexport function resolvePageRewrite(pathname: string, pages: SitePage[]): PageRewriteDecision {\n const current = pages.find((page) => page.path === pathname)\n\n if (current) {\n if (current.is_deleted) return { path: `${DELETED_PAGE_PREFIX}${pathname}` }\n // Renamed physical page: the file still lives at original_path, so rewrite there\n // internally while the browser keeps showing the new canonical path.\n if (current.is_physical && current.original_path && current.original_path !== current.path) {\n return { path: current.original_path }\n }\n return null\n }\n\n // Old URL of a renamed physical page — no redirect, it just no longer resolves to\n // anything (whether or not the page has since also been deleted).\n const oldUrlOfRenamed = pages.find(\n (page) => page.is_physical && page.original_path === pathname && page.path !== pathname,\n )\n if (oldUrlOfRenamed) return { path: `${DELETED_PAGE_PREFIX}${pathname}` }\n\n return null\n}\n\nexport type SitePageResolution =\n | { kind: 'not-found' }\n | { kind: 'duplicate'; sourceSegment: string; page: SitePage }\n | { kind: 'blank'; page: SitePage }\n\n// Catch-all route lookup: given the route's path segments, resolve which page (if any) this\n// request maps to. Callers still own the dynamic `import()` for `kind: 'duplicate'` — that\n// needs a literal relative path per app for webpack's static context analysis to work, so it\n// can't live in this shared package (see the comment at the call site).\nexport async function resolveSitePage(segments: string[], subdomainOverride?: string): Promise<SitePageResolution> {\n if (`/${segments[0]}` === DELETED_PAGE_PREFIX) return { kind: 'not-found' }\n\n const path = `/${segments.join('/')}`\n const pages = await fetchSitePages(subdomainOverride)\n const page = pages.find((entry) => entry.path === path && !entry.is_deleted)\n if (!page) return { kind: 'not-found' }\n\n if (page.duplicated_from) {\n const sourceSegment = page.duplicated_from === '/' ? '' : page.duplicated_from.replace(/^\\//, '')\n return { kind: 'duplicate', sourceSegment, page }\n }\n\n return { kind: 'blank', page }\n}\n","import { NextRequest, NextResponse } from 'next/server'\nimport { fetchSitePages, resolvePageRewrite, resolveSubdomain } from './site-pages'\n\n// Drop-in Next.js middleware for the OHH-670 page-CRUD system: rewrites deleted/renamed\n// pages to the right place before the catch-all route (see `resolveSitePage`) ever runs.\n// Apps that need extra middleware logic of their own can still compose `fetchSitePages`/\n// `resolvePageRewrite` directly instead of using this wrapper.\nexport async function sitePagesMiddleware(request: NextRequest): Promise<NextResponse> {\n const { pathname } = request.nextUrl\n\n if (pathname.startsWith('/_next') || pathname.startsWith('/api') || /\\.[a-zA-Z0-9]+$/.test(pathname)) {\n return NextResponse.next()\n }\n\n // `?subdomain=` is the canvas editor iframe's override (its own origin isn't the site's\n // real domain). Every other request — every real visitor — hits the site's actual\n // `*.ohhwells.site`/custom domain, so the request's own hostname is the source of truth\n // there; without this fallback the middleware silently no-ops on every production request.\n const subdomain =\n request.nextUrl.searchParams.get('subdomain') || resolveSubdomain(request.nextUrl.hostname)\n const pages = await fetchSitePages(subdomain || undefined)\n if (pages.length === 0) return NextResponse.next()\n\n const decision = resolvePageRewrite(pathname, pages)\n if (!decision) return NextResponse.next()\n return NextResponse.rewrite(new URL(decision.path, request.url))\n}\n\n// Mirrors the `_next`/`api` early-return above so apps that re-export this directly as\n// their middleware `config` don't invoke the function needlessly on asset requests.\nexport const sitePagesMiddlewareConfig = {\n matcher: ['/((?!_next|api).*)'],\n}\n","import { headers } from 'next/headers'\nimport { notFound } from 'next/navigation'\nimport { createElement, type ComponentType, type ReactElement } from 'react'\nimport { resolveSitePage, resolveSubdomain, type SitePage } from './site-pages'\n\nexport interface CatchAllPageHandlers {\n // Called for a page that's a duplicate of another. Must contain the actual `import(...)`\n // call itself (relative, not the `@` alias) — webpack can only build a static context\n // module (bundling every matching src/app/*/page.tsx) when the prefix is a real relative\n // path, so this one expression has to stay in the calling app's own file, resolved against\n // its own src/app tree, not this shared package's. Everything else about turning the\n // resolved module into a rendered element lives here instead.\n renderDuplicate: (sourceSegment: string) => Promise<{ default: ComponentType }>\n // Called for a page with no section content of its own yet.\n renderBlank: (page: SitePage) => ReactElement\n}\n\n// Full catch-all route resolution for the OHH-670 page-CRUD system: looks the page up,\n// calls `notFound()` for anything unresolved, and delegates to the two things every\n// consuming app still owns (the duplicate-source import and its blank-page chrome).\nexport async function renderCatchAllPage(\n segments: string[],\n subdomainOverride: string | undefined,\n handlers: CatchAllPageHandlers,\n): Promise<ReactElement> {\n // `subdomainOverride` is the canvas editor iframe's `?subdomain=` query param — its own\n // origin isn't the site's real domain. Every real visitor hits the site's actual\n // `*.ohhwells.site`/custom domain, so fall back to the request's own Host header there,\n // mirroring `sitePagesMiddleware`'s hostname fallback.\n const host = (await headers()).get('host') ?? undefined\n const subdomain = subdomainOverride || resolveSubdomain(host) || undefined\n const result = await resolveSitePage(segments, subdomain)\n\n if (result.kind === 'not-found') notFound()\n\n if (result.kind === 'duplicate') {\n try {\n const sourceModule = await handlers.renderDuplicate(result.sourceSegment)\n return createElement(sourceModule.default)\n } catch {\n notFound()\n }\n }\n\n return handlers.renderBlank(result.page)\n}\n"],"mappings":"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","names":[]}
|
package/dist/pages.d.cts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { ComponentType, ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
declare const DELETED_PAGE_PREFIX = "/__ohw-deleted";
|
|
5
|
+
type SitePage = {
|
|
6
|
+
id: string;
|
|
7
|
+
path: string;
|
|
8
|
+
title: string;
|
|
9
|
+
is_physical: boolean;
|
|
10
|
+
original_path: string | null;
|
|
11
|
+
duplicated_from: string | null;
|
|
12
|
+
is_deleted: boolean;
|
|
13
|
+
};
|
|
14
|
+
declare function resolveSubdomain(hostnameOverride?: string): string;
|
|
15
|
+
declare function fetchSitePages(subdomainOverride?: string): Promise<SitePage[]>;
|
|
16
|
+
type PageRewriteDecision = {
|
|
17
|
+
path: string;
|
|
18
|
+
} | null;
|
|
19
|
+
declare function resolvePageRewrite(pathname: string, pages: SitePage[]): PageRewriteDecision;
|
|
20
|
+
type SitePageResolution = {
|
|
21
|
+
kind: 'not-found';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'duplicate';
|
|
24
|
+
sourceSegment: string;
|
|
25
|
+
page: SitePage;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'blank';
|
|
28
|
+
page: SitePage;
|
|
29
|
+
};
|
|
30
|
+
declare function resolveSitePage(segments: string[], subdomainOverride?: string): Promise<SitePageResolution>;
|
|
31
|
+
|
|
32
|
+
declare function sitePagesMiddleware(request: NextRequest): Promise<NextResponse>;
|
|
33
|
+
declare const sitePagesMiddlewareConfig: {
|
|
34
|
+
matcher: string[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
interface CatchAllPageHandlers {
|
|
38
|
+
renderDuplicate: (sourceSegment: string) => Promise<{
|
|
39
|
+
default: ComponentType;
|
|
40
|
+
}>;
|
|
41
|
+
renderBlank: (page: SitePage) => ReactElement;
|
|
42
|
+
}
|
|
43
|
+
declare function renderCatchAllPage(segments: string[], subdomainOverride: string | undefined, handlers: CatchAllPageHandlers): Promise<ReactElement>;
|
|
44
|
+
|
|
45
|
+
export { type CatchAllPageHandlers, DELETED_PAGE_PREFIX, type PageRewriteDecision, type SitePage, type SitePageResolution, fetchSitePages, renderCatchAllPage, resolvePageRewrite, resolveSitePage, resolveSubdomain, sitePagesMiddleware, sitePagesMiddlewareConfig };
|
package/dist/pages.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { ComponentType, ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
declare const DELETED_PAGE_PREFIX = "/__ohw-deleted";
|
|
5
|
+
type SitePage = {
|
|
6
|
+
id: string;
|
|
7
|
+
path: string;
|
|
8
|
+
title: string;
|
|
9
|
+
is_physical: boolean;
|
|
10
|
+
original_path: string | null;
|
|
11
|
+
duplicated_from: string | null;
|
|
12
|
+
is_deleted: boolean;
|
|
13
|
+
};
|
|
14
|
+
declare function resolveSubdomain(hostnameOverride?: string): string;
|
|
15
|
+
declare function fetchSitePages(subdomainOverride?: string): Promise<SitePage[]>;
|
|
16
|
+
type PageRewriteDecision = {
|
|
17
|
+
path: string;
|
|
18
|
+
} | null;
|
|
19
|
+
declare function resolvePageRewrite(pathname: string, pages: SitePage[]): PageRewriteDecision;
|
|
20
|
+
type SitePageResolution = {
|
|
21
|
+
kind: 'not-found';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'duplicate';
|
|
24
|
+
sourceSegment: string;
|
|
25
|
+
page: SitePage;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'blank';
|
|
28
|
+
page: SitePage;
|
|
29
|
+
};
|
|
30
|
+
declare function resolveSitePage(segments: string[], subdomainOverride?: string): Promise<SitePageResolution>;
|
|
31
|
+
|
|
32
|
+
declare function sitePagesMiddleware(request: NextRequest): Promise<NextResponse>;
|
|
33
|
+
declare const sitePagesMiddlewareConfig: {
|
|
34
|
+
matcher: string[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
interface CatchAllPageHandlers {
|
|
38
|
+
renderDuplicate: (sourceSegment: string) => Promise<{
|
|
39
|
+
default: ComponentType;
|
|
40
|
+
}>;
|
|
41
|
+
renderBlank: (page: SitePage) => ReactElement;
|
|
42
|
+
}
|
|
43
|
+
declare function renderCatchAllPage(segments: string[], subdomainOverride: string | undefined, handlers: CatchAllPageHandlers): Promise<ReactElement>;
|
|
44
|
+
|
|
45
|
+
export { type CatchAllPageHandlers, DELETED_PAGE_PREFIX, type PageRewriteDecision, type SitePage, type SitePageResolution, fetchSitePages, renderCatchAllPage, resolvePageRewrite, resolveSitePage, resolveSubdomain, sitePagesMiddleware, sitePagesMiddlewareConfig };
|
package/dist/pages.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/lib/site-pages.ts
|
|
2
|
+
var DELETED_PAGE_PREFIX = "/__ohw-deleted";
|
|
3
|
+
function resolveSubdomain(hostnameOverride) {
|
|
4
|
+
if (hostnameOverride) {
|
|
5
|
+
const parts = hostnameOverride.split(".");
|
|
6
|
+
if (parts.length >= 3 && parts[0] !== "www") return parts[0];
|
|
7
|
+
}
|
|
8
|
+
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL;
|
|
9
|
+
if (!siteUrl) return "";
|
|
10
|
+
try {
|
|
11
|
+
const parts = new URL(siteUrl).hostname.split(".");
|
|
12
|
+
if (parts.length >= 3 && parts[0] !== "www") return parts[0];
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
async function fetchSitePages(subdomainOverride) {
|
|
18
|
+
const subdomain = subdomainOverride || resolveSubdomain();
|
|
19
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL;
|
|
20
|
+
if (!subdomain || !apiUrl) return [];
|
|
21
|
+
try {
|
|
22
|
+
const res = await fetch(`${apiUrl}/api/public/sites/${subdomain}/pages`, {
|
|
23
|
+
cache: "no-store"
|
|
24
|
+
});
|
|
25
|
+
if (!res.ok) return [];
|
|
26
|
+
const { pages } = await res.json();
|
|
27
|
+
return pages ?? [];
|
|
28
|
+
} catch {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function resolvePageRewrite(pathname, pages) {
|
|
33
|
+
const current = pages.find((page) => page.path === pathname);
|
|
34
|
+
if (current) {
|
|
35
|
+
if (current.is_deleted) return { path: `${DELETED_PAGE_PREFIX}${pathname}` };
|
|
36
|
+
if (current.is_physical && current.original_path && current.original_path !== current.path) {
|
|
37
|
+
return { path: current.original_path };
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const oldUrlOfRenamed = pages.find(
|
|
42
|
+
(page) => page.is_physical && page.original_path === pathname && page.path !== pathname
|
|
43
|
+
);
|
|
44
|
+
if (oldUrlOfRenamed) return { path: `${DELETED_PAGE_PREFIX}${pathname}` };
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
async function resolveSitePage(segments, subdomainOverride) {
|
|
48
|
+
if (`/${segments[0]}` === DELETED_PAGE_PREFIX) return { kind: "not-found" };
|
|
49
|
+
const path = `/${segments.join("/")}`;
|
|
50
|
+
const pages = await fetchSitePages(subdomainOverride);
|
|
51
|
+
const page = pages.find((entry) => entry.path === path && !entry.is_deleted);
|
|
52
|
+
if (!page) return { kind: "not-found" };
|
|
53
|
+
if (page.duplicated_from) {
|
|
54
|
+
const sourceSegment = page.duplicated_from === "/" ? "" : page.duplicated_from.replace(/^\//, "");
|
|
55
|
+
return { kind: "duplicate", sourceSegment, page };
|
|
56
|
+
}
|
|
57
|
+
return { kind: "blank", page };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/lib/site-pages-middleware.ts
|
|
61
|
+
import { NextResponse } from "next/server";
|
|
62
|
+
async function sitePagesMiddleware(request) {
|
|
63
|
+
const { pathname } = request.nextUrl;
|
|
64
|
+
if (pathname.startsWith("/_next") || pathname.startsWith("/api") || /\.[a-zA-Z0-9]+$/.test(pathname)) {
|
|
65
|
+
return NextResponse.next();
|
|
66
|
+
}
|
|
67
|
+
const subdomain = request.nextUrl.searchParams.get("subdomain") || resolveSubdomain(request.nextUrl.hostname);
|
|
68
|
+
const pages = await fetchSitePages(subdomain || void 0);
|
|
69
|
+
if (pages.length === 0) return NextResponse.next();
|
|
70
|
+
const decision = resolvePageRewrite(pathname, pages);
|
|
71
|
+
if (!decision) return NextResponse.next();
|
|
72
|
+
return NextResponse.rewrite(new URL(decision.path, request.url));
|
|
73
|
+
}
|
|
74
|
+
var sitePagesMiddlewareConfig = {
|
|
75
|
+
matcher: ["/((?!_next|api).*)"]
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/lib/site-pages-render.ts
|
|
79
|
+
import { headers } from "next/headers";
|
|
80
|
+
import { notFound } from "next/navigation";
|
|
81
|
+
import { createElement } from "react";
|
|
82
|
+
async function renderCatchAllPage(segments, subdomainOverride, handlers) {
|
|
83
|
+
const host = (await headers()).get("host") ?? void 0;
|
|
84
|
+
const subdomain = subdomainOverride || resolveSubdomain(host) || void 0;
|
|
85
|
+
const result = await resolveSitePage(segments, subdomain);
|
|
86
|
+
if (result.kind === "not-found") notFound();
|
|
87
|
+
if (result.kind === "duplicate") {
|
|
88
|
+
try {
|
|
89
|
+
const sourceModule = await handlers.renderDuplicate(result.sourceSegment);
|
|
90
|
+
return createElement(sourceModule.default);
|
|
91
|
+
} catch {
|
|
92
|
+
notFound();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return handlers.renderBlank(result.page);
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
DELETED_PAGE_PREFIX,
|
|
99
|
+
fetchSitePages,
|
|
100
|
+
renderCatchAllPage,
|
|
101
|
+
resolvePageRewrite,
|
|
102
|
+
resolveSitePage,
|
|
103
|
+
resolveSubdomain,
|
|
104
|
+
sitePagesMiddleware,
|
|
105
|
+
sitePagesMiddlewareConfig
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/site-pages.ts","../src/lib/site-pages-middleware.ts","../src/lib/site-pages-render.ts"],"sourcesContent":["// Shared page-CRUD infra (OHH-670): fetching a site's page list and deciding how the\n// catch-all route / middleware should handle deleted, renamed, and duplicated pages.\n// Server-safe (no React/browser APIs) so it can run in middleware (Edge runtime) and\n// Server Components — kept out of the main client-bundled entry point, see `../pages.ts`.\n\n// Prefix used to route deleted-physical-page requests into the catch-all `[...page]`\n// route, which has no file of its own at that segment and calls notFound() for it.\nexport const DELETED_PAGE_PREFIX = '/__ohw-deleted'\n\nexport type SitePage = {\n id: string\n path: string\n title: string\n is_physical: boolean\n original_path: string | null\n duplicated_from: string | null\n is_deleted: boolean\n}\n\n// Mirrors OhhwellsBridge's client-side resolveSubdomain: prefer the real request hostname\n// (window.location isn't available on the server, so callers pass the Host header/nextUrl\n// hostname instead) and only fall back to the NEXT_PUBLIC_SITE_URL env var when no hostname\n// is known — the only case that's true in local dev, where the host is just localhost.\nexport function resolveSubdomain(hostnameOverride?: string): string {\n if (hostnameOverride) {\n const parts = hostnameOverride.split('.')\n if (parts.length >= 3 && parts[0] !== 'www') return parts[0]\n }\n\n const siteUrl = process.env.NEXT_PUBLIC_SITE_URL\n if (!siteUrl) return ''\n try {\n const parts = new URL(siteUrl).hostname.split('.')\n if (parts.length >= 3 && parts[0] !== 'www') return parts[0]\n } catch {\n // ignore malformed env value\n }\n return ''\n}\n\n// `subdomainOverride` is the `?subdomain=` query param the canvas editor's iframe appends\n// (see `editUrl` in fo-class-experience). It's required locally: NEXT_PUBLIC_SITE_URL is\n// `http://localhost:3000` in dev, which resolveSubdomain() can't parse a subdomain from.\nexport async function fetchSitePages(subdomainOverride?: string): Promise<SitePage[]> {\n const subdomain = subdomainOverride || resolveSubdomain()\n const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL\n if (!subdomain || !apiUrl) return []\n\n try {\n // no-store, not a timed revalidate: middleware uses this list to decide whether a\n // path is deleted/renamed, and `next start`'s persistent Data Cache would otherwise\n // keep routing a just-deleted page's URL to its live content for longer than expected.\n const res = await fetch(`${apiUrl}/api/public/sites/${subdomain}/pages`, {\n cache: 'no-store',\n })\n if (!res.ok) return []\n const { pages } = (await res.json()) as { pages?: SitePage[] }\n\n // A reply without a list is not a list of none — the endpoint answers 200 with an empty body\n // when its own lookup failed. Handing that straight back put `undefined` into middleware and\n // took the whole site down with a 500 on every request.\n return pages ?? []\n } catch {\n return []\n }\n}\n\nexport type PageRewriteDecision = { path: string } | null\n\n// Middleware decision logic: given the current pathname and the site's page list, decide\n// whether to rewrite to the deleted-page placeholder or to a renamed physical page's real\n// file location. Callers still own the `_next`/`api`/static-file early-return and the actual\n// `NextResponse.rewrite` call, since those are Next.js-specific.\nexport function resolvePageRewrite(pathname: string, pages: SitePage[]): PageRewriteDecision {\n const current = pages.find((page) => page.path === pathname)\n\n if (current) {\n if (current.is_deleted) return { path: `${DELETED_PAGE_PREFIX}${pathname}` }\n // Renamed physical page: the file still lives at original_path, so rewrite there\n // internally while the browser keeps showing the new canonical path.\n if (current.is_physical && current.original_path && current.original_path !== current.path) {\n return { path: current.original_path }\n }\n return null\n }\n\n // Old URL of a renamed physical page — no redirect, it just no longer resolves to\n // anything (whether or not the page has since also been deleted).\n const oldUrlOfRenamed = pages.find(\n (page) => page.is_physical && page.original_path === pathname && page.path !== pathname,\n )\n if (oldUrlOfRenamed) return { path: `${DELETED_PAGE_PREFIX}${pathname}` }\n\n return null\n}\n\nexport type SitePageResolution =\n | { kind: 'not-found' }\n | { kind: 'duplicate'; sourceSegment: string; page: SitePage }\n | { kind: 'blank'; page: SitePage }\n\n// Catch-all route lookup: given the route's path segments, resolve which page (if any) this\n// request maps to. Callers still own the dynamic `import()` for `kind: 'duplicate'` — that\n// needs a literal relative path per app for webpack's static context analysis to work, so it\n// can't live in this shared package (see the comment at the call site).\nexport async function resolveSitePage(segments: string[], subdomainOverride?: string): Promise<SitePageResolution> {\n if (`/${segments[0]}` === DELETED_PAGE_PREFIX) return { kind: 'not-found' }\n\n const path = `/${segments.join('/')}`\n const pages = await fetchSitePages(subdomainOverride)\n const page = pages.find((entry) => entry.path === path && !entry.is_deleted)\n if (!page) return { kind: 'not-found' }\n\n if (page.duplicated_from) {\n const sourceSegment = page.duplicated_from === '/' ? '' : page.duplicated_from.replace(/^\\//, '')\n return { kind: 'duplicate', sourceSegment, page }\n }\n\n return { kind: 'blank', page }\n}\n","import { NextRequest, NextResponse } from 'next/server'\nimport { fetchSitePages, resolvePageRewrite, resolveSubdomain } from './site-pages'\n\n// Drop-in Next.js middleware for the OHH-670 page-CRUD system: rewrites deleted/renamed\n// pages to the right place before the catch-all route (see `resolveSitePage`) ever runs.\n// Apps that need extra middleware logic of their own can still compose `fetchSitePages`/\n// `resolvePageRewrite` directly instead of using this wrapper.\nexport async function sitePagesMiddleware(request: NextRequest): Promise<NextResponse> {\n const { pathname } = request.nextUrl\n\n if (pathname.startsWith('/_next') || pathname.startsWith('/api') || /\\.[a-zA-Z0-9]+$/.test(pathname)) {\n return NextResponse.next()\n }\n\n // `?subdomain=` is the canvas editor iframe's override (its own origin isn't the site's\n // real domain). Every other request — every real visitor — hits the site's actual\n // `*.ohhwells.site`/custom domain, so the request's own hostname is the source of truth\n // there; without this fallback the middleware silently no-ops on every production request.\n const subdomain =\n request.nextUrl.searchParams.get('subdomain') || resolveSubdomain(request.nextUrl.hostname)\n const pages = await fetchSitePages(subdomain || undefined)\n if (pages.length === 0) return NextResponse.next()\n\n const decision = resolvePageRewrite(pathname, pages)\n if (!decision) return NextResponse.next()\n return NextResponse.rewrite(new URL(decision.path, request.url))\n}\n\n// Mirrors the `_next`/`api` early-return above so apps that re-export this directly as\n// their middleware `config` don't invoke the function needlessly on asset requests.\nexport const sitePagesMiddlewareConfig = {\n matcher: ['/((?!_next|api).*)'],\n}\n","import { headers } from 'next/headers'\nimport { notFound } from 'next/navigation'\nimport { createElement, type ComponentType, type ReactElement } from 'react'\nimport { resolveSitePage, resolveSubdomain, type SitePage } from './site-pages'\n\nexport interface CatchAllPageHandlers {\n // Called for a page that's a duplicate of another. Must contain the actual `import(...)`\n // call itself (relative, not the `@` alias) — webpack can only build a static context\n // module (bundling every matching src/app/*/page.tsx) when the prefix is a real relative\n // path, so this one expression has to stay in the calling app's own file, resolved against\n // its own src/app tree, not this shared package's. Everything else about turning the\n // resolved module into a rendered element lives here instead.\n renderDuplicate: (sourceSegment: string) => Promise<{ default: ComponentType }>\n // Called for a page with no section content of its own yet.\n renderBlank: (page: SitePage) => ReactElement\n}\n\n// Full catch-all route resolution for the OHH-670 page-CRUD system: looks the page up,\n// calls `notFound()` for anything unresolved, and delegates to the two things every\n// consuming app still owns (the duplicate-source import and its blank-page chrome).\nexport async function renderCatchAllPage(\n segments: string[],\n subdomainOverride: string | undefined,\n handlers: CatchAllPageHandlers,\n): Promise<ReactElement> {\n // `subdomainOverride` is the canvas editor iframe's `?subdomain=` query param — its own\n // origin isn't the site's real domain. Every real visitor hits the site's actual\n // `*.ohhwells.site`/custom domain, so fall back to the request's own Host header there,\n // mirroring `sitePagesMiddleware`'s hostname fallback.\n const host = (await headers()).get('host') ?? undefined\n const subdomain = subdomainOverride || resolveSubdomain(host) || undefined\n const result = await resolveSitePage(segments, subdomain)\n\n if (result.kind === 'not-found') notFound()\n\n if (result.kind === 'duplicate') {\n try {\n const sourceModule = await handlers.renderDuplicate(result.sourceSegment)\n return createElement(sourceModule.default)\n } catch {\n notFound()\n }\n }\n\n return handlers.renderBlank(result.page)\n}\n"],"mappings":"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","names":[]}
|
package/dist/social-glyphs.cjs
CHANGED
|
@@ -46,7 +46,7 @@ function socialGlyphBody(platform) {
|
|
|
46
46
|
return GLYPH_BODIES[key] ?? GLYPH_ALIASES[key] ?? SOCIAL_GLYPH_FALLBACK;
|
|
47
47
|
}
|
|
48
48
|
function socialGlyphMarkup(platform) {
|
|
49
|
-
return "<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' aria-hidden='true'>" + socialGlyphBody(platform) + "</svg>";
|
|
49
|
+
return "<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' aria-hidden='true' style='display:block'>" + socialGlyphBody(platform) + "</svg>";
|
|
50
50
|
}
|
|
51
51
|
function socialGlyphPlatforms() {
|
|
52
52
|
return Object.keys(GLYPH_BODIES);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/social-glyphs.ts","../src/lib/social-glyphs.ts"],"sourcesContent":["/**\n * Server-safe entry for the social marks.\n *\n * The package's main entry is a client module — it carries a \"use client\" banner and React hooks —\n * so a template rendering its footer on the server received a client reference instead of a\n * function. These helpers are plain strings and nothing else, so they ship separately and can be\n * called anywhere: at build time, on the server, in the browser.\n */\nexport { socialGlyphBody, socialGlyphMarkup, socialGlyphPlatforms, SOCIAL_GLYPH_FALLBACK } from './lib/social-glyphs'\nexport type { SocialPlatform } from './lib/social-glyphs'\n","/**\n * Brand marks for social rows, drawn once for the whole product.\n *\n * They live here because the bridge is the one thing installed in every template and updated by a\n * single publish. While each side kept its own copy — the editor from one icon package, a template\n * from another or from an outside service — the mark that shipped with a template and the mark the\n * editor inserted came from different sets and looked nothing alike (OHH-762). Anything reading\n * from here cannot drift.\n *\n * Outlines in the lucide hand (ISC licensed): a 24 unit box, strokes on `currentColor`, so a mark\n * takes the colour and size of the words beside it.\n */\n\nconst GLYPH_BODIES = {\n facebook: \"<path d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z' />\",\n instagram: \"<rect width='20' height='20' x='2' y='2' rx='5' ry='5' /><path d='M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z' /><line x1='17.5' x2='17.51' y1='6.5' y2='6.5' />\",\n youtube: \"<path d='M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17' /><path d='m10 15 5-3-5-3z' />\",\n linkedin: \"<path d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z' /><rect width='4' height='12' x='2' y='9' /><circle cx='4' cy='4' r='2' />\",\n twitter: \"<path d='M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z' />\",\n} as const\n\n/** Same mark under the names a template or an owner might use. */\nconst GLYPH_ALIASES: Record<string, string> = {\n 'x': GLYPH_BODIES.twitter,\n 'yt': GLYPH_BODIES.youtube,\n 'linked-in': GLYPH_BODIES.linkedin,\n}\n\n/** Drawn for a platform we ship no mark for — a link is still a link. */\nexport const SOCIAL_GLYPH_FALLBACK =\n \"<circle cx='12' cy='12' r='10' /><path d='M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20' /><path d='M2 12h20' />\"\n\nexport type SocialPlatform = keyof typeof GLYPH_BODIES\n\n/** The body of the mark — paths only, so a caller can wrap it in its own sized svg. */\nexport function socialGlyphBody(platform: string): string {\n const key = platform.trim().toLowerCase()\n\n return (GLYPH_BODIES as Record<string, string>)[key] ?? GLYPH_ALIASES[key] ?? SOCIAL_GLYPH_FALLBACK\n}\n\n/** A complete mark, ready to drop into an icon slot. Size comes from the surrounding font size. */\nexport function socialGlyphMarkup(platform: string): string {\n return (\n \"<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' \" +\n \"fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' \" +\n \"stroke-linejoin='round' aria-hidden='true'>\" +\n socialGlyphBody(platform) +\n \"</svg>\"\n )\n}\n\n/** Platforms this set draws, for a picker or a template listing what it supports. */\nexport function socialGlyphPlatforms(): string[] {\n return Object.keys(GLYPH_BODIES)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaA,IAAM,eAAe;AAAA,EACnB,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AACX;AAGA,IAAM,gBAAwC;AAAA,EAC5C,KAAK,aAAa;AAAA,EAClB,MAAM,aAAa;AAAA,EACnB,aAAa,aAAa;AAC5B;AAGO,IAAM,wBACX;AAKK,SAAS,gBAAgB,UAA0B;AACxD,QAAM,MAAM,SAAS,KAAK,EAAE,YAAY;AAExC,SAAQ,aAAwC,GAAG,KAAK,cAAc,GAAG,KAAK;AAChF;AAGO,SAAS,kBAAkB,UAA0B;AAC1D,SACE,
|
|
1
|
+
{"version":3,"sources":["../src/social-glyphs.ts","../src/lib/social-glyphs.ts"],"sourcesContent":["/**\n * Server-safe entry for the social marks.\n *\n * The package's main entry is a client module — it carries a \"use client\" banner and React hooks —\n * so a template rendering its footer on the server received a client reference instead of a\n * function. These helpers are plain strings and nothing else, so they ship separately and can be\n * called anywhere: at build time, on the server, in the browser.\n */\nexport { socialGlyphBody, socialGlyphMarkup, socialGlyphPlatforms, SOCIAL_GLYPH_FALLBACK } from './lib/social-glyphs'\nexport type { SocialPlatform } from './lib/social-glyphs'\n","/**\n * Brand marks for social rows, drawn once for the whole product.\n *\n * They live here because the bridge is the one thing installed in every template and updated by a\n * single publish. While each side kept its own copy — the editor from one icon package, a template\n * from another or from an outside service — the mark that shipped with a template and the mark the\n * editor inserted came from different sets and looked nothing alike (OHH-762). Anything reading\n * from here cannot drift.\n *\n * Outlines in the lucide hand (ISC licensed): a 24 unit box, strokes on `currentColor`, so a mark\n * takes the colour and size of the words beside it.\n */\n\nconst GLYPH_BODIES = {\n facebook: \"<path d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z' />\",\n instagram: \"<rect width='20' height='20' x='2' y='2' rx='5' ry='5' /><path d='M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z' /><line x1='17.5' x2='17.51' y1='6.5' y2='6.5' />\",\n youtube: \"<path d='M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17' /><path d='m10 15 5-3-5-3z' />\",\n linkedin: \"<path d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z' /><rect width='4' height='12' x='2' y='9' /><circle cx='4' cy='4' r='2' />\",\n twitter: \"<path d='M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z' />\",\n} as const\n\n/** Same mark under the names a template or an owner might use. */\nconst GLYPH_ALIASES: Record<string, string> = {\n 'x': GLYPH_BODIES.twitter,\n 'yt': GLYPH_BODIES.youtube,\n 'linked-in': GLYPH_BODIES.linkedin,\n}\n\n/** Drawn for a platform we ship no mark for — a link is still a link. */\nexport const SOCIAL_GLYPH_FALLBACK =\n \"<circle cx='12' cy='12' r='10' /><path d='M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20' /><path d='M2 12h20' />\"\n\nexport type SocialPlatform = keyof typeof GLYPH_BODIES\n\n/** The body of the mark — paths only, so a caller can wrap it in its own sized svg. */\nexport function socialGlyphBody(platform: string): string {\n const key = platform.trim().toLowerCase()\n\n return (GLYPH_BODIES as Record<string, string>)[key] ?? GLYPH_ALIASES[key] ?? SOCIAL_GLYPH_FALLBACK\n}\n\n/** A complete mark, ready to drop into an icon slot. Size comes from the surrounding font size. */\nexport function socialGlyphMarkup(platform: string): string {\n return (\n \"<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' \" +\n \"fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' \" +\n // display:block: an inline default reserves a few px below the mark for a descender it never\n // draws, so a row centring this against words beside it (OHH-766) leaves the glyph looking\n // pushed up out of that phantom gap.\n \"stroke-linejoin='round' aria-hidden='true' style='display:block'>\" +\n socialGlyphBody(platform) +\n \"</svg>\"\n )\n}\n\n/** Platforms this set draws, for a picker or a template listing what it supports. */\nexport function socialGlyphPlatforms(): string[] {\n return Object.keys(GLYPH_BODIES)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaA,IAAM,eAAe;AAAA,EACnB,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AACX;AAGA,IAAM,gBAAwC;AAAA,EAC5C,KAAK,aAAa;AAAA,EAClB,MAAM,aAAa;AAAA,EACnB,aAAa,aAAa;AAC5B;AAGO,IAAM,wBACX;AAKK,SAAS,gBAAgB,UAA0B;AACxD,QAAM,MAAM,SAAS,KAAK,EAAE,YAAY;AAExC,SAAQ,aAAwC,GAAG,KAAK,cAAc,GAAG,KAAK;AAChF;AAGO,SAAS,kBAAkB,UAA0B;AAC1D,SACE,uOAMA,gBAAgB,QAAQ,IACxB;AAEJ;AAGO,SAAS,uBAAiC;AAC/C,SAAO,OAAO,KAAK,YAAY;AACjC;","names":[]}
|
package/dist/social-glyphs.js
CHANGED
|
@@ -17,7 +17,7 @@ function socialGlyphBody(platform) {
|
|
|
17
17
|
return GLYPH_BODIES[key] ?? GLYPH_ALIASES[key] ?? SOCIAL_GLYPH_FALLBACK;
|
|
18
18
|
}
|
|
19
19
|
function socialGlyphMarkup(platform) {
|
|
20
|
-
return "<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' aria-hidden='true'>" + socialGlyphBody(platform) + "</svg>";
|
|
20
|
+
return "<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' aria-hidden='true' style='display:block'>" + socialGlyphBody(platform) + "</svg>";
|
|
21
21
|
}
|
|
22
22
|
function socialGlyphPlatforms() {
|
|
23
23
|
return Object.keys(GLYPH_BODIES);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/social-glyphs.ts"],"sourcesContent":["/**\n * Brand marks for social rows, drawn once for the whole product.\n *\n * They live here because the bridge is the one thing installed in every template and updated by a\n * single publish. While each side kept its own copy — the editor from one icon package, a template\n * from another or from an outside service — the mark that shipped with a template and the mark the\n * editor inserted came from different sets and looked nothing alike (OHH-762). Anything reading\n * from here cannot drift.\n *\n * Outlines in the lucide hand (ISC licensed): a 24 unit box, strokes on `currentColor`, so a mark\n * takes the colour and size of the words beside it.\n */\n\nconst GLYPH_BODIES = {\n facebook: \"<path d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z' />\",\n instagram: \"<rect width='20' height='20' x='2' y='2' rx='5' ry='5' /><path d='M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z' /><line x1='17.5' x2='17.51' y1='6.5' y2='6.5' />\",\n youtube: \"<path d='M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17' /><path d='m10 15 5-3-5-3z' />\",\n linkedin: \"<path d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z' /><rect width='4' height='12' x='2' y='9' /><circle cx='4' cy='4' r='2' />\",\n twitter: \"<path d='M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z' />\",\n} as const\n\n/** Same mark under the names a template or an owner might use. */\nconst GLYPH_ALIASES: Record<string, string> = {\n 'x': GLYPH_BODIES.twitter,\n 'yt': GLYPH_BODIES.youtube,\n 'linked-in': GLYPH_BODIES.linkedin,\n}\n\n/** Drawn for a platform we ship no mark for — a link is still a link. */\nexport const SOCIAL_GLYPH_FALLBACK =\n \"<circle cx='12' cy='12' r='10' /><path d='M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20' /><path d='M2 12h20' />\"\n\nexport type SocialPlatform = keyof typeof GLYPH_BODIES\n\n/** The body of the mark — paths only, so a caller can wrap it in its own sized svg. */\nexport function socialGlyphBody(platform: string): string {\n const key = platform.trim().toLowerCase()\n\n return (GLYPH_BODIES as Record<string, string>)[key] ?? GLYPH_ALIASES[key] ?? SOCIAL_GLYPH_FALLBACK\n}\n\n/** A complete mark, ready to drop into an icon slot. Size comes from the surrounding font size. */\nexport function socialGlyphMarkup(platform: string): string {\n return (\n \"<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' \" +\n \"fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' \" +\n \"stroke-linejoin='round' aria-hidden='true'>\" +\n socialGlyphBody(platform) +\n \"</svg>\"\n )\n}\n\n/** Platforms this set draws, for a picker or a template listing what it supports. */\nexport function socialGlyphPlatforms(): string[] {\n return Object.keys(GLYPH_BODIES)\n}\n"],"mappings":";AAaA,IAAM,eAAe;AAAA,EACnB,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AACX;AAGA,IAAM,gBAAwC;AAAA,EAC5C,KAAK,aAAa;AAAA,EAClB,MAAM,aAAa;AAAA,EACnB,aAAa,aAAa;AAC5B;AAGO,IAAM,wBACX;AAKK,SAAS,gBAAgB,UAA0B;AACxD,QAAM,MAAM,SAAS,KAAK,EAAE,YAAY;AAExC,SAAQ,aAAwC,GAAG,KAAK,cAAc,GAAG,KAAK;AAChF;AAGO,SAAS,kBAAkB,UAA0B;AAC1D,SACE,
|
|
1
|
+
{"version":3,"sources":["../src/lib/social-glyphs.ts"],"sourcesContent":["/**\n * Brand marks for social rows, drawn once for the whole product.\n *\n * They live here because the bridge is the one thing installed in every template and updated by a\n * single publish. While each side kept its own copy — the editor from one icon package, a template\n * from another or from an outside service — the mark that shipped with a template and the mark the\n * editor inserted came from different sets and looked nothing alike (OHH-762). Anything reading\n * from here cannot drift.\n *\n * Outlines in the lucide hand (ISC licensed): a 24 unit box, strokes on `currentColor`, so a mark\n * takes the colour and size of the words beside it.\n */\n\nconst GLYPH_BODIES = {\n facebook: \"<path d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z' />\",\n instagram: \"<rect width='20' height='20' x='2' y='2' rx='5' ry='5' /><path d='M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z' /><line x1='17.5' x2='17.51' y1='6.5' y2='6.5' />\",\n youtube: \"<path d='M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17' /><path d='m10 15 5-3-5-3z' />\",\n linkedin: \"<path d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z' /><rect width='4' height='12' x='2' y='9' /><circle cx='4' cy='4' r='2' />\",\n twitter: \"<path d='M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z' />\",\n} as const\n\n/** Same mark under the names a template or an owner might use. */\nconst GLYPH_ALIASES: Record<string, string> = {\n 'x': GLYPH_BODIES.twitter,\n 'yt': GLYPH_BODIES.youtube,\n 'linked-in': GLYPH_BODIES.linkedin,\n}\n\n/** Drawn for a platform we ship no mark for — a link is still a link. */\nexport const SOCIAL_GLYPH_FALLBACK =\n \"<circle cx='12' cy='12' r='10' /><path d='M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20' /><path d='M2 12h20' />\"\n\nexport type SocialPlatform = keyof typeof GLYPH_BODIES\n\n/** The body of the mark — paths only, so a caller can wrap it in its own sized svg. */\nexport function socialGlyphBody(platform: string): string {\n const key = platform.trim().toLowerCase()\n\n return (GLYPH_BODIES as Record<string, string>)[key] ?? GLYPH_ALIASES[key] ?? SOCIAL_GLYPH_FALLBACK\n}\n\n/** A complete mark, ready to drop into an icon slot. Size comes from the surrounding font size. */\nexport function socialGlyphMarkup(platform: string): string {\n return (\n \"<svg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24' \" +\n \"fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' \" +\n // display:block: an inline default reserves a few px below the mark for a descender it never\n // draws, so a row centring this against words beside it (OHH-766) leaves the glyph looking\n // pushed up out of that phantom gap.\n \"stroke-linejoin='round' aria-hidden='true' style='display:block'>\" +\n socialGlyphBody(platform) +\n \"</svg>\"\n )\n}\n\n/** Platforms this set draws, for a picker or a template listing what it supports. */\nexport function socialGlyphPlatforms(): string[] {\n return Object.keys(GLYPH_BODIES)\n}\n"],"mappings":";AAaA,IAAM,eAAe;AAAA,EACnB,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AACX;AAGA,IAAM,gBAAwC;AAAA,EAC5C,KAAK,aAAa;AAAA,EAClB,MAAM,aAAa;AAAA,EACnB,aAAa,aAAa;AAC5B;AAGO,IAAM,wBACX;AAKK,SAAS,gBAAgB,UAA0B;AACxD,QAAM,MAAM,SAAS,KAAK,EAAE,YAAY;AAExC,SAAQ,aAAwC,GAAG,KAAK,cAAc,GAAG,KAAK;AAChF;AAGO,SAAS,kBAAkB,UAA0B;AAC1D,SACE,uOAMA,gBAAgB,QAAQ,IACxB;AAEJ;AAGO,SAAS,uBAAiC;AAC/C,SAAO,OAAO,KAAK,YAAY;AACjC;","names":[]}
|
package/dist/styles.css
CHANGED
|
@@ -104,6 +104,9 @@
|
|
|
104
104
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .inset-0, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).inset-0 {
|
|
105
105
|
inset: calc(var(--spacing) * 0);
|
|
106
106
|
}
|
|
107
|
+
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .inset-y-0, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).inset-y-0 {
|
|
108
|
+
inset-block: calc(var(--spacing) * 0);
|
|
109
|
+
}
|
|
107
110
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .top-0, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).top-0 {
|
|
108
111
|
top: calc(var(--spacing) * 0);
|
|
109
112
|
}
|
|
@@ -298,6 +301,9 @@
|
|
|
298
301
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\!h-full, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\!h-full {
|
|
299
302
|
height: 100% !important;
|
|
300
303
|
}
|
|
304
|
+
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .h-2, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).h-2 {
|
|
305
|
+
height: calc(var(--spacing) * 2);
|
|
306
|
+
}
|
|
301
307
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .h-4, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).h-4 {
|
|
302
308
|
height: calc(var(--spacing) * 4);
|
|
303
309
|
}
|
|
@@ -514,6 +520,11 @@
|
|
|
514
520
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .resize, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).resize {
|
|
515
521
|
resize: both;
|
|
516
522
|
}
|
|
523
|
+
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .appearance-none, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).appearance-none {
|
|
524
|
+
-webkit-appearance: none;
|
|
525
|
+
-moz-appearance: none;
|
|
526
|
+
appearance: none;
|
|
527
|
+
}
|
|
517
528
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .grid-cols-3, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).grid-cols-3 {
|
|
518
529
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
519
530
|
}
|
|
@@ -1043,6 +1054,9 @@
|
|
|
1043
1054
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .text-foreground\!, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).text-foreground\! {
|
|
1044
1055
|
color: var(--color-foreground) !important;
|
|
1045
1056
|
}
|
|
1057
|
+
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .text-muted, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).text-muted {
|
|
1058
|
+
color: var(--color-muted);
|
|
1059
|
+
}
|
|
1046
1060
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .text-muted-foreground, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).text-muted-foreground {
|
|
1047
1061
|
color: var(--color-muted-foreground);
|
|
1048
1062
|
}
|
|
@@ -1070,6 +1084,9 @@
|
|
|
1070
1084
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .capitalize, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).capitalize {
|
|
1071
1085
|
text-transform: capitalize;
|
|
1072
1086
|
}
|
|
1087
|
+
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .uppercase, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).uppercase {
|
|
1088
|
+
text-transform: uppercase;
|
|
1089
|
+
}
|
|
1073
1090
|
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .italic, :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).italic {
|
|
1074
1091
|
font-style: italic;
|
|
1075
1092
|
}
|
|
@@ -1208,6 +1225,9 @@
|
|
|
1208
1225
|
-moz-user-select: none;
|
|
1209
1226
|
user-select: none;
|
|
1210
1227
|
}
|
|
1228
|
+
:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[ow\:scheduling\], :is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[ow\:scheduling\] {
|
|
1229
|
+
ow: scheduling;
|
|
1230
|
+
}
|
|
1211
1231
|
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .placeholder\:text-muted-foreground,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).placeholder\:text-muted-foreground)::-moz-placeholder {
|
|
1212
1232
|
color: var(--color-muted-foreground);
|
|
1213
1233
|
}
|
|
@@ -1627,6 +1647,44 @@
|
|
|
1627
1647
|
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&_svg\:not\(\[class\*\=absolute\]\)\]\:relative,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&_svg\:not\(\[class\*\=absolute\]\)\]\:relative) svg:not([class*=absolute]) {
|
|
1628
1648
|
position: relative;
|
|
1629
1649
|
}
|
|
1650
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-moz-range-thumb\]\:size-5,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-moz-range-thumb\]\:size-5)::-moz-range-thumb {
|
|
1651
|
+
width: calc(var(--spacing) * 5);
|
|
1652
|
+
height: calc(var(--spacing) * 5);
|
|
1653
|
+
}
|
|
1654
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-moz-range-thumb\]\:rounded-full,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-moz-range-thumb\]\:rounded-full)::-moz-range-thumb {
|
|
1655
|
+
border-radius: calc(infinity * 1px);
|
|
1656
|
+
}
|
|
1657
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-moz-range-thumb\]\:border-2,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-moz-range-thumb\]\:border-2)::-moz-range-thumb {
|
|
1658
|
+
border-style: var(--tw-border-style);
|
|
1659
|
+
border-width: 2px;
|
|
1660
|
+
}
|
|
1661
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-moz-range-thumb\]\:border-primary,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-moz-range-thumb\]\:border-primary)::-moz-range-thumb {
|
|
1662
|
+
border-color: var(--color-primary);
|
|
1663
|
+
}
|
|
1664
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-moz-range-thumb\]\:bg-background,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-moz-range-thumb\]\:bg-background)::-moz-range-thumb {
|
|
1665
|
+
background-color: var(--color-background);
|
|
1666
|
+
}
|
|
1667
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-webkit-slider-thumb\]\:size-5,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-webkit-slider-thumb\]\:size-5)::-webkit-slider-thumb {
|
|
1668
|
+
width: calc(var(--spacing) * 5);
|
|
1669
|
+
height: calc(var(--spacing) * 5);
|
|
1670
|
+
}
|
|
1671
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-webkit-slider-thumb\]\:appearance-none,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-webkit-slider-thumb\]\:appearance-none)::-webkit-slider-thumb {
|
|
1672
|
+
-webkit-appearance: none;
|
|
1673
|
+
appearance: none;
|
|
1674
|
+
}
|
|
1675
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-webkit-slider-thumb\]\:rounded-full,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-webkit-slider-thumb\]\:rounded-full)::-webkit-slider-thumb {
|
|
1676
|
+
border-radius: calc(infinity * 1px);
|
|
1677
|
+
}
|
|
1678
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-webkit-slider-thumb\]\:border-2,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-webkit-slider-thumb\]\:border-2)::-webkit-slider-thumb {
|
|
1679
|
+
border-style: var(--tw-border-style);
|
|
1680
|
+
border-width: 2px;
|
|
1681
|
+
}
|
|
1682
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-webkit-slider-thumb\]\:border-primary,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-webkit-slider-thumb\]\:border-primary)::-webkit-slider-thumb {
|
|
1683
|
+
border-color: var(--color-primary);
|
|
1684
|
+
}
|
|
1685
|
+
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\:\:-webkit-slider-thumb\]\:bg-background,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\:\:-webkit-slider-thumb\]\:bg-background)::-webkit-slider-thumb {
|
|
1686
|
+
background-color: var(--color-background);
|
|
1687
|
+
}
|
|
1630
1688
|
:is(:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]) .\[\&\>svg\:first-child\]\:absolute,:is([data-ohw-bridge-root],[data-ohw-bridge],[data-radix-popper-content-wrapper],[data-slot="dropdown-menu-content"],[data-slot="popover-content"],[data-slot="tooltip-content"],[data-ohw-field-type-picker],[data-ohw-section-container="scheduling"],[data-ohw-scheduling-modal]).\[\&\>svg\:first-child\]\:absolute) > svg:first-child {
|
|
1631
1689
|
position: absolute;
|
|
1632
1690
|
}
|