@birdycom/omniaui-react 0.12.0 → 0.12.2

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/manifest.json CHANGED
@@ -318,12 +318,24 @@
318
318
  "file": "src/components/LinkArrow.tsx",
319
319
  "snippet": "@birdycom/omniaui/snippets/link-arrow.html"
320
320
  },
321
+ {
322
+ "name": "link-row",
323
+ "kind": "component",
324
+ "file": "src/components/LinkRow.tsx",
325
+ "snippet": "@birdycom/omniaui/snippets/link-row.html"
326
+ },
321
327
  {
322
328
  "name": "list-toolbar",
323
329
  "kind": "component",
324
330
  "file": "src/components/ListToolbar.tsx",
325
331
  "snippet": "@birdycom/omniaui/snippets/list-toolbar.html"
326
332
  },
333
+ {
334
+ "name": "live-frame",
335
+ "kind": "component",
336
+ "file": "src/components/LiveFrame.tsx",
337
+ "snippet": "@birdycom/omniaui/snippets/live-frame.html"
338
+ },
327
339
  {
328
340
  "name": "marquee",
329
341
  "kind": "component",
@@ -642,6 +654,12 @@
642
654
  "file": "src/components/VersionBanner.tsx",
643
655
  "snippet": "@birdycom/omniaui/snippets/version-banner.html"
644
656
  },
657
+ {
658
+ "name": "watermark",
659
+ "kind": "component",
660
+ "file": "src/components/Watermark.tsx",
661
+ "snippet": "@birdycom/omniaui/snippets/watermark.html"
662
+ },
645
663
  {
646
664
  "name": "about-timeline",
647
665
  "kind": "block",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@birdycom/omniaui-react",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "OmniaUI for React: typed function components and page blocks that render the exact @birdycom/omniaui and @birdycom/omniaui-blocks markup.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,34 @@
1
+ // File: packages/react/src/components/LinkRow.tsx | Map: types -> LinkRow (ul.oc-link-row -> li > a per link, or children)
2
+ import { forwardRef } from "react";
3
+ import type { HTMLAttributes, ReactNode } from "react";
4
+ import { cx } from "../utils";
5
+
6
+ export interface LinkRowLink {
7
+ href: string;
8
+ label: ReactNode;
9
+ }
10
+
11
+ export interface LinkRowProps extends HTMLAttributes<HTMLUListElement> {
12
+ /** The links; external ones get an arrow and github.com links the GitHub mark (CSS, by the href). Or pass <li> children. */
13
+ links?: LinkRowLink[];
14
+ tone?: "default" | "accent" | "muted";
15
+ size?: "sm" | "default" | "lg";
16
+ children?: ReactNode;
17
+ }
18
+
19
+ const external = (href: string) => /^https?:\/\//.test(href);
20
+
21
+ /** `<ul class="oc-link-row">`: a row of links under a card, icons by the href. */
22
+ export const LinkRow = forwardRef<HTMLUListElement, LinkRowProps>(function LinkRow(
23
+ { links, tone = "default", size = "default", className, children, ...rest },
24
+ ref,
25
+ ) {
26
+ const classes = cx("oc-link-row", tone !== "default" && `oc-link-row--${tone}`, size !== "default" && `oc-link-row--${size}`, className);
27
+ return (
28
+ <ul ref={ref} className={classes} {...rest}>
29
+ {links
30
+ ? links.map((l, i) => <li key={i}><a href={l.href} rel={external(l.href) ? "noopener" : undefined}>{l.label}</a></li>)
31
+ : children}
32
+ </ul>
33
+ );
34
+ });
@@ -0,0 +1,37 @@
1
+ // File: packages/react/src/components/LiveFrame.tsx | Map: types -> LiveFrame (div.oc-live-frame + virtual size -> iframe or children)
2
+ import { forwardRef } from "react";
3
+ import type { CSSProperties, HTMLAttributes, ReactNode } from "react";
4
+ import { cx } from "../utils";
5
+
6
+ export interface LiveFrameProps extends HTMLAttributes<HTMLDivElement> {
7
+ /** Page to show in an iframe. Leave empty and pass children (an <img>, <video>, or .oc-live-frame__content). */
8
+ src?: string;
9
+ /** Accessible name of the iframe. */
10
+ title?: string;
11
+ /** Virtual size in px: the page is laid out at this size and scaled to the frame width. */
12
+ width?: number;
13
+ height?: number;
14
+ /** A picture of a page: clicks and scrolling pass through. */
15
+ static?: boolean;
16
+ /** Put the frame in the view slot of an OmniaUI browser frame (adds .oc-browser-frame__view). */
17
+ inBrowserFrame?: boolean;
18
+ children?: ReactNode;
19
+ }
20
+
21
+ /** `.oc-live-frame`: a live page at a virtual size, scaled down to the frame width in pure CSS. */
22
+ export const LiveFrame = forwardRef<HTMLDivElement, LiveFrameProps>(function LiveFrame(
23
+ { src, title = "", width = 1280, height = 720, static: isStatic = false, inBrowserFrame = false, className, style, children, ...rest },
24
+ ref,
25
+ ) {
26
+ const size = { "--oc-live-w": width, "--oc-live-h": height } as CSSProperties;
27
+ return (
28
+ <div
29
+ ref={ref}
30
+ className={cx(inBrowserFrame && "oc-browser-frame__view", "oc-live-frame", isStatic && "oc-live-frame--static", className)}
31
+ style={{ ...size, ...style }}
32
+ {...rest}
33
+ >
34
+ {src ? <iframe src={src} title={title} loading="lazy" scrolling="no" tabIndex={isStatic ? -1 : undefined} /> : children}
35
+ </div>
36
+ );
37
+ });
@@ -0,0 +1,35 @@
1
+ // File: packages/react/src/components/Watermark.tsx | Map: types -> Watermark (span.oc-watermark + modifiers, text once or tiled)
2
+ import { forwardRef, Fragment } from "react";
3
+ import type { HTMLAttributes, ReactNode } from "react";
4
+ import { cx } from "../utils";
5
+
6
+ export type WatermarkVariant = "diagonal" | "straight" | "tile" | "corner" | "corner-top";
7
+ export type WatermarkTone = "default" | "light" | "primary" | "destructive";
8
+
9
+ export interface WatermarkProps extends HTMLAttributes<HTMLSpanElement> {
10
+ /** The text ("Concept", "Draft"), or a logo (<img>) or icon (<svg>). */
11
+ text?: ReactNode;
12
+ variant?: WatermarkVariant;
13
+ tone?: WatermarkTone;
14
+ /** How often the text repeats with variant="tile". */
15
+ repeat?: number;
16
+ /** Turn an <img> logo into a flat gray stamp. */
17
+ mono?: boolean;
18
+ }
19
+
20
+ /**
21
+ * `<span class="oc-watermark">`: light text over its positioned parent (put it last inside an element with
22
+ * `className="relative"`). Click-through and aria-hidden: say "draft" in the content itself when it matters.
23
+ */
24
+ export const Watermark = forwardRef<HTMLSpanElement, WatermarkProps>(function Watermark(
25
+ { text = "Concept", variant = "diagonal", tone = "default", repeat = 12, mono = false, className, ...rest },
26
+ ref,
27
+ ) {
28
+ const classes = cx("oc-watermark", variant !== "diagonal" && `oc-watermark--${variant}`, tone !== "default" && `oc-watermark--${tone}`, mono && "oc-watermark--mono", className);
29
+ const count = variant === "tile" ? Math.max(1, repeat) : 1;
30
+ return (
31
+ <span ref={ref} className={classes} aria-hidden="true" {...rest}>
32
+ {Array.from({ length: count }, (_, i) => (typeof text === "string" || typeof text === "number" ? <span key={i}>{text}</span> : <Fragment key={i}>{text}</Fragment>))}
33
+ </span>
34
+ );
35
+ });
package/src/index.ts CHANGED
@@ -54,7 +54,9 @@ export * from "./components/LanguageSelect";
54
54
  export * from "./components/LauncherCard";
55
55
  export * from "./components/Lightbox";
56
56
  export * from "./components/LinkArrow";
57
+ export * from "./components/LinkRow";
57
58
  export * from "./components/ListToolbar";
59
+ export * from "./components/LiveFrame";
58
60
  export * from "./components/Marquee";
59
61
  export * from "./components/MediaCard";
60
62
  export * from "./components/MediaRow";
@@ -108,6 +110,7 @@ export * from "./components/Tree";
108
110
  export * from "./components/UpgradeBanner";
109
111
  export * from "./components/User";
110
112
  export * from "./components/VersionBanner";
113
+ export * from "./components/Watermark";
111
114
  export * from "./blocks/BlockAboutTimeline";
112
115
  export * from "./blocks/BlockAppHeader";
113
116
  export * from "./blocks/BlockAppShell";