@tempomedia/antarmuka 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +102 -0
  3. package/dist/components/Accordion/Accordion.d.ts +9 -0
  4. package/dist/components/Accordion/index.d.ts +1 -0
  5. package/dist/components/ActionButton/ActionButton.d.ts +27 -0
  6. package/dist/components/ActionButton/index.d.ts +1 -0
  7. package/dist/components/Alert/Alert.d.ts +11 -0
  8. package/dist/components/Alert/index.d.ts +1 -0
  9. package/dist/components/Avatar/Avatar.d.ts +14 -0
  10. package/dist/components/Avatar/index.d.ts +1 -0
  11. package/dist/components/Badge/Badge.d.ts +7 -0
  12. package/dist/components/Badge/index.d.ts +1 -0
  13. package/dist/components/Button/Button.d.ts +15 -0
  14. package/dist/components/Button/index.d.ts +1 -0
  15. package/dist/components/Card/Card.d.ts +6 -0
  16. package/dist/components/Card/index.d.ts +1 -0
  17. package/dist/components/Footer/Footer.d.ts +19 -0
  18. package/dist/components/Footer/index.d.ts +1 -0
  19. package/dist/components/Header/Header.d.ts +30 -0
  20. package/dist/components/Header/index.d.ts +1 -0
  21. package/dist/components/Input/Input.d.ts +9 -0
  22. package/dist/components/Input/index.d.ts +1 -0
  23. package/dist/components/Memberzone/Memberzone.d.ts +35 -0
  24. package/dist/components/Memberzone/MemberzoneMenus.d.ts +13 -0
  25. package/dist/components/Memberzone/MemberzonePanel.d.ts +29 -0
  26. package/dist/components/Memberzone/MemberzoneSection.d.ts +18 -0
  27. package/dist/components/Memberzone/SocialMedia.d.ts +9 -0
  28. package/dist/components/Memberzone/defaults.d.ts +7 -0
  29. package/dist/components/Memberzone/index.d.ts +7 -0
  30. package/dist/components/Memberzone/types.d.ts +39 -0
  31. package/dist/components/SearchMenu/SearchInput.d.ts +17 -0
  32. package/dist/components/SearchMenu/SearchSummary.d.ts +10 -0
  33. package/dist/components/SearchMenu/SearchTabs.d.ts +21 -0
  34. package/dist/components/SearchMenu/index.d.ts +3 -0
  35. package/dist/components/Sidebar/Sidebar.d.ts +39 -0
  36. package/dist/components/Sidebar/index.d.ts +1 -0
  37. package/dist/components/Spinner/Spinner.d.ts +9 -0
  38. package/dist/components/Spinner/index.d.ts +1 -0
  39. package/dist/components/Textarea/Textarea.d.ts +9 -0
  40. package/dist/components/Textarea/index.d.ts +1 -0
  41. package/dist/icons/header.d.ts +5 -0
  42. package/dist/icons/index.d.ts +5 -0
  43. package/dist/icons/logos.d.ts +7 -0
  44. package/dist/icons/menu.d.ts +15 -0
  45. package/dist/icons/search.d.ts +3 -0
  46. package/dist/icons/social.d.ts +11 -0
  47. package/dist/index.cjs +96 -0
  48. package/dist/index.d.ts +18 -0
  49. package/dist/index.js +6636 -0
  50. package/dist/style.css +1 -0
  51. package/dist/tokens/breakpoints.d.ts +9 -0
  52. package/dist/tokens/colors.d.ts +26 -0
  53. package/dist/tokens/index.d.ts +7 -0
  54. package/dist/tokens/radius.d.ts +10 -0
  55. package/dist/tokens/shadows.d.ts +7 -0
  56. package/dist/tokens/spacing.d.ts +15 -0
  57. package/dist/tokens/typography.d.ts +22 -0
  58. package/dist/tokens/zIndex.d.ts +11 -0
  59. package/dist/utils/cn.d.ts +6 -0
  60. package/package.json +84 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-06-18
9
+
10
+ ### Added
11
+
12
+ Initial MVP release — rewritten from the previous Nuxt 3 kit into a React component library.
13
+
14
+ - **Tooling**: Vite Library Mode (ESM + CJS + TypeScript declarations + `style.css`), Tailwind CSS v4, Storybook, Vitest + React Testing Library, ESLint + Prettier, GitHub Actions CI and tag-based publish.
15
+ - **Core components**: `Button`, `Input`, `Textarea`, `Badge`, `Card`, `Alert`, `Spinner`, `Avatar` — each with stories, tests, `className` support, and accessibility attributes.
16
+ - **Feature components**: `MemberzonePanel` and `Memberzone.*` Radix-based drawer primitives, `SocialMedia` — ported from the Nuxt Memberzone with the router/Nuxt coupling removed.
17
+ - **Design tokens**: colors, typography, spacing, radius, shadows, z-index, breakpoints.
18
+ - **Utilities**: `cn` class-merge helper; exported icon set.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # @tempo/antarmuka
2
+
3
+ Tempo's shared global UI component library for React products.
4
+
5
+ _Antarmuka_ means "interface" in Bahasa Indonesia — this package is Tempo's shared user interface layer, providing consistent, accessible, reusable components across React-based Tempo products (TanStack Start, Next.js, Astro React, Laravel Inertia React, internal tools).
6
+
7
+ Built with **React + TypeScript + Vite (Library Mode) + Tailwind CSS v4 + Storybook + Vitest**.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @tempo/antarmuka
13
+ ```
14
+
15
+ `react` and `react-dom` (>= 18) are peer dependencies.
16
+
17
+ ## Usage
18
+
19
+ Import the stylesheet once at your app's entry point, then use components anywhere:
20
+
21
+ ```tsx
22
+ // app entry (e.g. main.tsx)
23
+ import '@tempo/antarmuka/styles.css'
24
+ ```
25
+
26
+ ```tsx
27
+ import { Button, Input, MemberzonePanel } from '@tempo/antarmuka'
28
+
29
+ export default function Page() {
30
+ return (
31
+ <form>
32
+ <Input label="Email" placeholder="you@tempo.co" />
33
+ <Button variant="primary">Submit</Button>
34
+ </form>
35
+ )
36
+ }
37
+ ```
38
+
39
+ ### Memberzone (Tempo account drawer)
40
+
41
+ ```tsx
42
+ import { MemberzonePanel } from '@tempo/antarmuka'
43
+
44
+ <MemberzonePanel
45
+ user={{
46
+ id: 9896432,
47
+ fullname: 'Anjar Pratama',
48
+ email: 'anjar@tempo.co',
49
+ initial: 'An',
50
+ firstLetterOfName: 'A',
51
+ vipSubscription: false,
52
+ contentAccess: ['tempo_plus', 'teras_plus'],
53
+ }}
54
+ templateFor="tempo" // or "teras"
55
+ ssoUrl="https://sso.tempo.co"
56
+ side="right"
57
+ onLogout={() => signOut()} // optional; falls back to an SSO logout link
58
+ />
59
+ ```
60
+
61
+ The Memberzone is framework-agnostic: it has no router dependency. Active menu highlighting uses `window.location.pathname` by default, or pass `currentPath` explicitly.
62
+
63
+ ## Components
64
+
65
+ | Group | Components |
66
+ | --------- | ---------------------------------------------------------------- |
67
+ | Form | `Button`, `Input`, `Textarea` |
68
+ | Display | `Badge`, `Card`, `Alert`, `Spinner`, `Avatar` |
69
+ | Feature | `MemberzonePanel` + `Memberzone.*` primitives, `SocialMedia` |
70
+
71
+ Design tokens (`colors`, `typography`, `spacing`, `radius`, `shadows`, `zIndex`, `breakpoints`), the `cn` class-merge helper, and all icons are also exported.
72
+
73
+ ## Development
74
+
75
+ ```bash
76
+ npm install
77
+ npm run dev # Storybook on http://localhost:6006
78
+ npm run test # Vitest
79
+ npm run lint # ESLint
80
+ npm run typecheck # tsc --noEmit
81
+ npm run build # build dist/ (ESM + CJS + d.ts + style.css)
82
+ ```
83
+
84
+ ## Publishing
85
+
86
+ Publishing is automated via GitHub Actions on `v*` tags (see `.github/workflows/publish.yml`), running lint → typecheck → test → build → `npm publish --access restricted`. Requires the `NPM_TOKEN` secret.
87
+
88
+ Manual publish:
89
+
90
+ ```bash
91
+ npm login
92
+ npm run build
93
+ npm publish --access restricted
94
+ ```
95
+
96
+ ## Versioning
97
+
98
+ This package follows [Semantic Versioning](https://semver.org/). See [CHANGELOG.md](./CHANGELOG.md).
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,9 @@
1
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
2
+ /** Accordion root. Pass `type="single"` (collapsible) or `type="multiple"`. */
3
+ export declare const Accordion: import('react').ForwardRefExoticComponent<(AccordionPrimitive.AccordionSingleProps | AccordionPrimitive.AccordionMultipleProps) & import('react').RefAttributes<HTMLDivElement>>;
4
+ export declare const AccordionItem: import('react').ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionItemProps & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
5
+ export declare const AccordionTrigger: import('react').ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionTriggerProps & import('react').RefAttributes<HTMLButtonElement>, "ref"> & {
6
+ /** Hide the default chevron indicator. */
7
+ hideChevron?: boolean;
8
+ } & import('react').RefAttributes<HTMLButtonElement>>;
9
+ export declare const AccordionContent: import('react').ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionContentProps & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from './Accordion';
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from 'react';
2
+ import { VariantProps } from 'class-variance-authority';
3
+ /**
4
+ * Design-system button (the Figma "Button" component).
5
+ *
6
+ * Faithful to the spec: 1px border radius, `Primary-Main` (#D61D23) fill,
7
+ * Small = 32px tall with 8px/12px padding and an 8px gap. Distinct from the
8
+ * lighter {@link Button} primitive (which uses `rounded-sm`).
9
+ */
10
+ export declare const actionButtonVariants: (props?: ({
11
+ variant?: "primary" | "secondary" | null | undefined;
12
+ styleType?: "fill" | "outline" | null | undefined;
13
+ size?: "small" | "medium" | "large" | null | undefined;
14
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
15
+ export interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof actionButtonVariants> {
16
+ /** Show a loading spinner and disable interaction. */
17
+ loading?: boolean;
18
+ /** Icon node rendered before the label. Only shown when `showIconLeft` is true. */
19
+ iconLeft?: ReactNode;
20
+ /** Icon node rendered after the label. Only shown when `showIconRight` is true. */
21
+ iconRight?: ReactNode;
22
+ /** Toggle the left icon (Figma: Show Icon Left). Default false. */
23
+ showIconLeft?: boolean;
24
+ /** Toggle the right icon (Figma: Show Icon Right). Default false. */
25
+ showIconRight?: boolean;
26
+ }
27
+ export declare const ActionButton: import('react').ForwardRefExoticComponent<ActionButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1 @@
1
+ export { ActionButton, actionButtonVariants, type ActionButtonProps } from './ActionButton';
@@ -0,0 +1,11 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ export declare const alertVariants: (props?: ({
3
+ variant?: "danger" | "success" | "info" | "warning" | null | undefined;
4
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
5
+ export interface AlertProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof alertVariants> {
6
+ /** Optional bold title rendered above the content. */
7
+ title?: string;
8
+ /** Hide the leading status icon. */
9
+ hideIcon?: boolean;
10
+ }
11
+ export declare const Alert: import('react').ForwardRefExoticComponent<AlertProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ export { Alert, alertVariants, type AlertProps } from './Alert';
@@ -0,0 +1,14 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ export declare const avatarVariants: (props?: ({
3
+ size?: "sm" | "md" | "lg" | null | undefined;
4
+ bordered?: boolean | null | undefined;
5
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
+ export interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof avatarVariants> {
7
+ /** Image source. Falls back to initials when missing or it fails to load. */
8
+ src?: string;
9
+ /** Alt text for the image / accessible label. */
10
+ alt?: string;
11
+ /** Initials shown when no image is available. */
12
+ initials?: string;
13
+ }
14
+ export declare const Avatar: import('react').ForwardRefExoticComponent<AvatarProps & import('react').RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1 @@
1
+ export { Avatar, avatarVariants, type AvatarProps } from './Avatar';
@@ -0,0 +1,7 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ export declare const badgeVariants: (props?: ({
3
+ variant?: "danger" | "default" | "neutral" | "success" | null | undefined;
4
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
5
+ export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
6
+ }
7
+ export declare const Badge: import('react').ForwardRefExoticComponent<BadgeProps & import('react').RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1 @@
1
+ export { Badge, badgeVariants, type BadgeProps } from './Badge';
@@ -0,0 +1,15 @@
1
+ import { ReactNode } from 'react';
2
+ import { VariantProps } from 'class-variance-authority';
3
+ export declare const buttonVariants: (props?: ({
4
+ variant?: "primary" | "secondary" | "danger" | "ghost" | null | undefined;
5
+ size?: "sm" | "md" | "lg" | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
8
+ /** Show a loading spinner and disable interaction. */
9
+ loading?: boolean;
10
+ /** Optional icon rendered before the label (Show Icon Left). */
11
+ iconLeft?: ReactNode;
12
+ /** Optional icon rendered after the label (Show Icon Right). */
13
+ iconRight?: ReactNode;
14
+ }
15
+ export declare const Button: import('react').ForwardRefExoticComponent<ButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1 @@
1
+ export { Button, buttonVariants, type ButtonProps } from './Button';
@@ -0,0 +1,6 @@
1
+ export type CardProps = React.HTMLAttributes<HTMLDivElement>;
2
+ export declare const Card: import('react').ForwardRefExoticComponent<CardProps & import('react').RefAttributes<HTMLDivElement>>;
3
+ export declare const CardHeader: import('react').ForwardRefExoticComponent<CardProps & import('react').RefAttributes<HTMLDivElement>>;
4
+ export declare const CardTitle: import('react').ForwardRefExoticComponent<import('react').HTMLAttributes<HTMLHeadingElement> & import('react').RefAttributes<HTMLHeadingElement>>;
5
+ export declare const CardBody: import('react').ForwardRefExoticComponent<CardProps & import('react').RefAttributes<HTMLDivElement>>;
6
+ export declare const CardFooter: import('react').ForwardRefExoticComponent<CardProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ export { Card, CardHeader, CardTitle, CardBody, CardFooter, type CardProps, } from './Card';
@@ -0,0 +1,19 @@
1
+ /** Coordinated color scheme for the two footer variants. */
2
+ type FooterVariant = 'dark' | 'light';
3
+ export interface FooterProps extends React.HTMLAttributes<HTMLElement> {
4
+ /**
5
+ * Color scheme. `dark` (default) uses a #212121 background; `light` uses white.
6
+ * For a custom background, keep a variant for contrast and override via
7
+ * `className` (e.g. `<Footer className="bg-[#1a1a1a]" />`).
8
+ */
9
+ variant?: FooterVariant;
10
+ }
11
+ /**
12
+ * Desktop site footer for Tempo products.
13
+ *
14
+ * Contains the editorial quote, social links, app-download badges, the Tempo
15
+ * media network, informational links, trust badges, and a copyright bar.
16
+ * Mobile uses a separate footer component.
17
+ */
18
+ export declare function Footer({ className, variant, ...props }: FooterProps): import("react").JSX.Element;
19
+ export {};
@@ -0,0 +1 @@
1
+ export { Footer, type FooterProps } from './Footer';
@@ -0,0 +1,30 @@
1
+ import { ReactNode } from 'react';
2
+ export interface HeaderProps extends React.HTMLAttributes<HTMLElement> {
3
+ /** Brand logo — left on desktop, centered on mobile. Defaults to a Tempo placeholder. */
4
+ logo?: ReactNode;
5
+ /** Desktop navigation content rendered in the center of the bar. */
6
+ children?: ReactNode;
7
+ /** Desktop right-aligned content, e.g. the primary call-to-action button(s). */
8
+ actions?: ReactNode;
9
+ /** Pin the header to the top of the viewport (Scroll Position: Fixed). Default true. */
10
+ fixed?: boolean;
11
+ /** Mobile: click handler for the left menu / search button. */
12
+ onMenuClick?: () => void;
13
+ /** Mobile: click handler for the right user / login button. */
14
+ onUserClick?: () => void;
15
+ /** Mobile: accessible label for the menu button. */
16
+ menuLabel?: string;
17
+ /** Mobile: accessible label for the user button. */
18
+ userLabel?: string;
19
+ }
20
+ /**
21
+ * Responsive site header / top navigation bar.
22
+ *
23
+ * - **Mobile** (`< md`): 49px tall — logo on the left, user/login + menu/search
24
+ * buttons grouped on the right; 1px bottom border (#EEEEEE), 8px/24px padding.
25
+ * - **Desktop** (`>= md`): 64px tall — logo, optional centered nav, right-aligned
26
+ * actions; 1px bottom border (#E0E0E0), content capped at 1366px.
27
+ *
28
+ * Fixed to the top of the viewport by default.
29
+ */
30
+ export declare const Header: import('react').ForwardRefExoticComponent<HeaderProps & import('react').RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ export { Header, type HeaderProps } from './Header';
@@ -0,0 +1,9 @@
1
+ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
2
+ /** Visible label rendered above the field. */
3
+ label?: string;
4
+ /** Helper text rendered below the field. */
5
+ helperText?: string;
6
+ /** Error message; when set, the field is marked invalid. */
7
+ error?: string;
8
+ }
9
+ export declare const Input: import('react').ForwardRefExoticComponent<InputProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1 @@
1
+ export { Input, type InputProps } from './Input';
@@ -0,0 +1,35 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
3
+ export declare const memberzoneVariants: (props?: ({
4
+ side?: "left" | "right" | "top" | "bottom" | null | undefined;
5
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
+ export type MemberzoneSide = NonNullable<VariantProps<typeof memberzoneVariants>['side']>;
7
+ export interface MemberzoneContentProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>, VariantProps<typeof memberzoneVariants> {
8
+ /** Hide the built-in close (X) button. */
9
+ hideClose?: boolean;
10
+ }
11
+ /**
12
+ * Compound slide-in drawer built on Radix Dialog.
13
+ *
14
+ * @example
15
+ * <Memberzone.Root>
16
+ * <Memberzone.Trigger>Open</Memberzone.Trigger>
17
+ * <Memberzone.Content side="right">
18
+ * <Memberzone.Header>
19
+ * <Memberzone.Title>Akun</Memberzone.Title>
20
+ * </Memberzone.Header>
21
+ * </Memberzone.Content>
22
+ * </Memberzone.Root>
23
+ */
24
+ export declare const Memberzone: {
25
+ Root: import('react').FC<DialogPrimitive.DialogProps>;
26
+ Trigger: import('react').ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
27
+ Close: import('react').ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & import('react').RefAttributes<HTMLButtonElement>>;
28
+ Portal: import('react').FC<DialogPrimitive.DialogPortalProps>;
29
+ Overlay: import('react').ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
30
+ Content: import('react').ForwardRefExoticComponent<MemberzoneContentProps & import('react').RefAttributes<HTMLDivElement>>;
31
+ Header: import('react').ForwardRefExoticComponent<import('react').HTMLAttributes<HTMLDivElement> & import('react').RefAttributes<HTMLDivElement>>;
32
+ Footer: import('react').ForwardRefExoticComponent<import('react').HTMLAttributes<HTMLDivElement> & import('react').RefAttributes<HTMLDivElement>>;
33
+ Title: import('react').ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & import('react').RefAttributes<HTMLHeadingElement>, "ref"> & import('react').RefAttributes<HTMLHeadingElement>>;
34
+ Description: import('react').ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & import('react').RefAttributes<HTMLParagraphElement>, "ref"> & import('react').RefAttributes<HTMLParagraphElement>>;
35
+ };
@@ -0,0 +1,13 @@
1
+ import { MemberzoneTemplate, MemberzoneMenuItem } from './types';
2
+ export interface MemberzoneMenusProps {
3
+ templateFor: MemberzoneTemplate;
4
+ ssoUrl: string;
5
+ isSidebar?: boolean;
6
+ menuItems?: MemberzoneMenuItem[];
7
+ /** Active path for highlighting. Defaults to window.location.pathname. */
8
+ currentPath?: string;
9
+ /** Called when the user activates "Keluar". If omitted, an SSO logout link is used. */
10
+ onLogout?: () => void;
11
+ }
12
+ /** Account menu links + customer help + logout. Router-free (uses currentPath). */
13
+ export declare function MemberzoneMenus({ templateFor, ssoUrl, isSidebar, menuItems, currentPath, onLogout, }: MemberzoneMenusProps): import("react").JSX.Element;
@@ -0,0 +1,29 @@
1
+ import { MemberzoneSide } from './Memberzone';
2
+ import { MemberzoneUser, MemberzoneTemplate, MemberzoneSubscription, MemberzoneMenuItem, SocialLink } from './types';
3
+ export interface MemberzonePanelProps {
4
+ user: MemberzoneUser;
5
+ templateFor: MemberzoneTemplate;
6
+ ssoUrl: string;
7
+ /** Side the drawer slides in from. Defaults to "right". */
8
+ side?: Extract<MemberzoneSide, 'left' | 'right'>;
9
+ subscriptions?: MemberzoneSubscription[];
10
+ menuItems?: MemberzoneMenuItem[];
11
+ socialLinks?: SocialLink[];
12
+ /** Active path for menu highlighting. Defaults to window.location.pathname. */
13
+ currentPath?: string;
14
+ /** Called when the user activates "Keluar" (logout). */
15
+ onLogout?: () => void;
16
+ /** Controlled open state (optional). */
17
+ open?: boolean;
18
+ defaultOpen?: boolean;
19
+ onOpenChange?: (open: boolean) => void;
20
+ /** Title shown in the drawer header. */
21
+ title?: string;
22
+ className?: string;
23
+ }
24
+ /**
25
+ * Tempo member account drawer: an avatar trigger that opens a slide-in panel
26
+ * with the user's info, subscription status, account menus, and (for Teras)
27
+ * social links. Framework-agnostic — no router dependency.
28
+ */
29
+ export declare function MemberzonePanel({ user, templateFor, ssoUrl, side, subscriptions, menuItems, socialLinks, currentPath, onLogout, open, defaultOpen, onOpenChange, title, className, }: MemberzonePanelProps): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { MemberzoneUser, MemberzoneTemplate, MemberzoneSubscription, MemberzoneMenuItem, SocialLink } from './types';
2
+ export interface MemberzoneSectionProps {
3
+ user: MemberzoneUser;
4
+ templateFor: MemberzoneTemplate;
5
+ ssoUrl: string;
6
+ /** When true, renders compact (no subscription panel) — e.g. inline sidebar usage. */
7
+ isSidebar?: boolean;
8
+ subscriptions?: MemberzoneSubscription[];
9
+ menuItems?: MemberzoneMenuItem[];
10
+ socialLinks?: SocialLink[];
11
+ /** Active path for menu highlighting. Defaults to window.location.pathname. */
12
+ currentPath?: string;
13
+ /** Called when the user activates "Keluar" (logout). */
14
+ onLogout?: () => void;
15
+ className?: string;
16
+ }
17
+ /** User info + subscription status + account menus. The body of the Memberzone drawer. */
18
+ export declare function MemberzoneSection({ user, templateFor, ssoUrl, isSidebar, subscriptions, menuItems, socialLinks, currentPath, onLogout, className, }: MemberzoneSectionProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { SocialLink } from './types';
2
+ export interface SocialMediaProps {
3
+ /** Heading shown above the icons. */
4
+ title?: string;
5
+ /** Social links to render. Defaults to the Teras set. */
6
+ links?: SocialLink[];
7
+ }
8
+ /** Row of social media icons (used in the Teras Memberzone template). */
9
+ export declare function SocialMedia({ title, links }: SocialMediaProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { MemberzoneSubscription, MemberzoneMenuItem, SocialLink } from './types';
2
+ /** Default Tempo subscription rows (Tempo Plus, Teras, Tempo VIP). */
3
+ export declare const defaultSubscriptions: MemberzoneSubscription[];
4
+ /** Default account menu links. */
5
+ export declare const defaultMenuItems: MemberzoneMenuItem[];
6
+ /** Default Teras social media links. */
7
+ export declare const defaultTerasSocials: SocialLink[];
@@ -0,0 +1,7 @@
1
+ export { Memberzone, memberzoneVariants, type MemberzoneSide, type MemberzoneContentProps } from './Memberzone';
2
+ export { MemberzonePanel, type MemberzonePanelProps } from './MemberzonePanel';
3
+ export { MemberzoneSection, type MemberzoneSectionProps } from './MemberzoneSection';
4
+ export { MemberzoneMenus, type MemberzoneMenusProps } from './MemberzoneMenus';
5
+ export { SocialMedia, type SocialMediaProps } from './SocialMedia';
6
+ export { defaultSubscriptions, defaultMenuItems, defaultTerasSocials } from './defaults';
7
+ export type { MemberzoneUser, MemberzoneTemplate, MemberzoneSubscription, MemberzoneMenuItem, SocialLink, } from './types';
@@ -0,0 +1,39 @@
1
+ import { ComponentType, SVGProps } from 'react';
2
+ /** Which product the Memberzone is being rendered for. Controls ordering/menu rules. */
3
+ export type MemberzoneTemplate = 'tempo' | 'teras';
4
+ /** Minimal user shape required to render the Memberzone panel. */
5
+ export interface MemberzoneUser {
6
+ id: number | string;
7
+ fullname: string;
8
+ email: string;
9
+ /** Initials shown in the large avatar (e.g. "An"). */
10
+ initial: string;
11
+ /** Single letter shown in the small trigger avatar (e.g. "A"). */
12
+ firstLetterOfName: string;
13
+ /** Whether the VIP subscription is active. */
14
+ vipSubscription?: boolean;
15
+ /** Content access keys, e.g. ["tempo_plus", "teras_plus"]. */
16
+ contentAccess?: string[];
17
+ }
18
+ /** A subscription row in the status panel. */
19
+ export interface MemberzoneSubscription {
20
+ name: string;
21
+ link: string;
22
+ icon: ComponentType<SVGProps<SVGSVGElement>>;
23
+ /** content_access key used to determine active status (omitted for VIP). */
24
+ accessKey?: string;
25
+ /** Set to true to treat this row as the VIP subscription. */
26
+ isVip?: boolean;
27
+ }
28
+ /** An account menu link. */
29
+ export interface MemberzoneMenuItem {
30
+ key: string;
31
+ label: string;
32
+ href: string;
33
+ icon: ComponentType<SVGProps<SVGSVGElement>>;
34
+ }
35
+ /** A social media link rendered in the Teras template. */
36
+ export interface SocialLink {
37
+ name: string;
38
+ url: string;
39
+ }
@@ -0,0 +1,17 @@
1
+ export interface SearchInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'onSubmit'> {
2
+ /** Controlled input value. */
3
+ value: string;
4
+ /** Called on every keystroke with the new value. */
5
+ onValueChange?: (value: string) => void;
6
+ /** Called when the form is submitted (Enter or the search button). */
7
+ onSubmit?: (value: string) => void;
8
+ /** Called when the clear (×) button is pressed. Defaults to submitting an empty value. */
9
+ onClear?: () => void;
10
+ }
11
+ /**
12
+ * Search text field with a submit (search) button and a clear (×) button.
13
+ *
14
+ * Router-free: it surfaces `onValueChange` / `onSubmit` / `onClear` callbacks and
15
+ * lets the consumer decide how to navigate or fetch results.
16
+ */
17
+ export declare const SearchInput: import('react').ForwardRefExoticComponent<SearchInputProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,10 @@
1
+ export interface SearchSummaryProps extends React.HTMLAttributes<HTMLDivElement> {
2
+ /** Result category label, e.g. "ARTIKEL". */
3
+ category: string;
4
+ /** Number of matching results. */
5
+ count: number;
6
+ /** The search keyword that produced these results. */
7
+ query?: string;
8
+ }
9
+ /** Heading + result-count summary shown above a list of search results. */
10
+ export declare function SearchSummary({ category, count, query, className, ...props }: SearchSummaryProps): import("react").JSX.Element;
@@ -0,0 +1,21 @@
1
+ export interface SearchTab {
2
+ label: string;
3
+ /** Unique identifier; compared against `activeValue` to mark the active tab. */
4
+ value: string;
5
+ /** Optional link target. When set the tab renders as an `<a>`; otherwise a `<button>`. */
6
+ href?: string;
7
+ }
8
+ export interface SearchTabsProps extends React.HTMLAttributes<HTMLDivElement> {
9
+ tabs: SearchTab[];
10
+ /** The `value` of the currently active tab. */
11
+ activeValue: string;
12
+ /** Called with the tab `value` when a button-mode tab is clicked. */
13
+ onTabChange?: (value: string) => void;
14
+ }
15
+ /**
16
+ * Tab bar for the search menu (e.g. Artikel / Mingguan).
17
+ *
18
+ * Router-free: provide `href` for link tabs, or omit it and handle `onTabChange`
19
+ * for button tabs. The active tab is highlighted with the brand underline.
20
+ */
21
+ export declare function SearchTabs({ tabs, activeValue, onTabChange, className, ...props }: SearchTabsProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ export { SearchInput, type SearchInputProps } from './SearchInput';
2
+ export { SearchSummary, type SearchSummaryProps } from './SearchSummary';
3
+ export { SearchTabs, type SearchTabsProps, type SearchTab } from './SearchTabs';
@@ -0,0 +1,39 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
3
+ export declare const sidebarVariants: (props?: ({
4
+ side?: "left" | "right" | null | undefined;
5
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
+ export type SidebarSide = NonNullable<VariantProps<typeof sidebarVariants>['side']>;
7
+ export interface SidebarContentProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>, VariantProps<typeof sidebarVariants> {
8
+ /** Hide the built-in close (X) button. */
9
+ hideClose?: boolean;
10
+ }
11
+ /**
12
+ * Slide-in navigation sidebar built on Radix Dialog.
13
+ *
14
+ * A generic, data-free drawer: compose the menu content (links, {@link Accordion},
15
+ * a search field, etc.) inside `Sidebar.Body`. Router- and fetch-agnostic.
16
+ *
17
+ * @example
18
+ * <Sidebar.Root>
19
+ * <Sidebar.Trigger>Menu</Sidebar.Trigger>
20
+ * <Sidebar.Content side="left">
21
+ * <Sidebar.Header>
22
+ * <Sidebar.Title>Menu</Sidebar.Title>
23
+ * </Sidebar.Header>
24
+ * <Sidebar.Body>…</Sidebar.Body>
25
+ * </Sidebar.Content>
26
+ * </Sidebar.Root>
27
+ */
28
+ export declare const Sidebar: {
29
+ Root: import('react').FC<DialogPrimitive.DialogProps>;
30
+ Trigger: import('react').ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
31
+ Close: import('react').ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & import('react').RefAttributes<HTMLButtonElement>>;
32
+ Portal: import('react').FC<DialogPrimitive.DialogPortalProps>;
33
+ Overlay: import('react').ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
34
+ Content: import('react').ForwardRefExoticComponent<SidebarContentProps & import('react').RefAttributes<HTMLDivElement>>;
35
+ Header: import('react').ForwardRefExoticComponent<import('react').HTMLAttributes<HTMLDivElement> & import('react').RefAttributes<HTMLDivElement>>;
36
+ Title: import('react').ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & import('react').RefAttributes<HTMLHeadingElement>, "ref"> & import('react').RefAttributes<HTMLHeadingElement>>;
37
+ Description: import('react').ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & import('react').RefAttributes<HTMLParagraphElement>, "ref"> & import('react').RefAttributes<HTMLParagraphElement>>;
38
+ Body: import('react').ForwardRefExoticComponent<import('react').HTMLAttributes<HTMLDivElement> & import('react').RefAttributes<HTMLDivElement>>;
39
+ };
@@ -0,0 +1 @@
1
+ export { Sidebar, sidebarVariants, type SidebarSide, type SidebarContentProps } from './Sidebar';
@@ -0,0 +1,9 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ export declare const spinnerVariants: (props?: ({
3
+ size?: "sm" | "md" | "lg" | null | undefined;
4
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
5
+ export interface SpinnerProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof spinnerVariants> {
6
+ /** Accessible label announced to screen readers. */
7
+ label?: string;
8
+ }
9
+ export declare const Spinner: import('react').ForwardRefExoticComponent<SpinnerProps & import('react').RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1 @@
1
+ export { Spinner, spinnerVariants, type SpinnerProps } from './Spinner';
@@ -0,0 +1,9 @@
1
+ export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
2
+ /** Visible label rendered above the field. */
3
+ label?: string;
4
+ /** Helper text rendered below the field. */
5
+ helperText?: string;
6
+ /** Error message; when set, the field is marked invalid. */
7
+ error?: string;
8
+ }
9
+ export declare const Textarea: import('react').ForwardRefExoticComponent<TextareaProps & import('react').RefAttributes<HTMLTextAreaElement>>;
@@ -0,0 +1 @@
1
+ export { Textarea, type TextareaProps } from './Textarea';
@@ -0,0 +1,5 @@
1
+ import { SVGProps } from 'react';
2
+ /** Combined menu + search icon (from the mobile header's Menu.svg). */
3
+ export declare function MenuSearchIcon({ className, ...props }: SVGProps<SVGSVGElement>): import("react").JSX.Element;
4
+ /** User / account icon (from the mobile header's User Icon.svg). */
5
+ export declare function UserCircleIcon({ className, ...props }: SVGProps<SVGSVGElement>): import("react").JSX.Element;