@sirendesign/markup 1.0.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.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Optional: Initialize Firebase at your app root level
3
+ *
4
+ * This allows you to initialize Firebase ONCE for your entire application,
5
+ * then use multiple MarkupWidget instances that all share the same Firebase app.
6
+ *
7
+ * Usage:
8
+ *
9
+ * // In your main App.tsx or index.tsx
10
+ * import { initFirebase } from '@siren/markup/initFirebase';
11
+ *
12
+ * initFirebase({
13
+ * apiKey: "...",
14
+ * authDomain: "...",
15
+ * projectId: "...",
16
+ * storageBucket: "...",
17
+ * messagingSenderId: "...",
18
+ * appId: "..."
19
+ * });
20
+ *
21
+ * // Then in your components, just use the widget without firebaseConfig:
22
+ * <MarkupWidget config={{ projectId: 'website-a' }} />
23
+ * <MarkupWidget config={{ projectId: 'website-b' }} />
24
+ *
25
+ * Both widgets will use the same Firebase app but different projectId for isolation.
26
+ */
27
+ export { initializeFirebase as initFirebase } from './services/firebase';
28
+ export type { FirebaseConfig } from './services/firebase';
@@ -0,0 +1,11 @@
1
+ import { User, UserCredential } from 'firebase/auth';
2
+ export interface AuthUser {
3
+ uid: string;
4
+ email: string | null;
5
+ displayName: string | null;
6
+ }
7
+ export declare const signUp: (email: string, password: string) => Promise<UserCredential>;
8
+ export declare const signIn: (email: string, password: string) => Promise<UserCredential>;
9
+ export declare const logOut: () => Promise<void>;
10
+ export declare const onAuthChange: (callback: (user: User | null) => void) => import("@firebase/util").Unsubscribe;
11
+ export declare const getCurrentUser: () => User | null;
@@ -0,0 +1,31 @@
1
+ import { FirebaseApp } from "firebase/app";
2
+ import { Auth } from "firebase/auth";
3
+ import { Firestore } from "firebase/firestore";
4
+ export interface FirebaseConfig {
5
+ apiKey: string;
6
+ authDomain: string;
7
+ projectId: string;
8
+ storageBucket: string;
9
+ messagingSenderId: string;
10
+ appId: string;
11
+ }
12
+ /**
13
+ * Initialize Firebase app if not already initialized.
14
+ * Multiple calls with the same or different configs will reuse the first initialized app.
15
+ * This ensures only ONE Firebase app instance exists across all widgets.
16
+ *
17
+ * @param config - Firebase configuration object
18
+ */
19
+ export declare const initializeFirebase: (config: FirebaseConfig) => {
20
+ app: FirebaseApp;
21
+ auth: Auth;
22
+ db: Firestore;
23
+ };
24
+ /**
25
+ * Get Firebase Auth instance. Throws if Firebase not initialized.
26
+ */
27
+ export declare const getFirebaseAuth: () => Auth;
28
+ /**
29
+ * Get Firestore Database instance. Throws if Firebase not initialized.
30
+ */
31
+ export declare const getFirebaseDb: () => Firestore;
@@ -0,0 +1,11 @@
1
+ import { Timestamp } from 'firebase/firestore';
2
+ import { FeedbackItem } from '../types';
3
+ export interface FirestoreFeedback extends Omit<FeedbackItem, 'id' | 'createdAt'> {
4
+ projectId: string;
5
+ userId: string;
6
+ createdAt: Timestamp;
7
+ }
8
+ export declare const createFeedback: (feedback: Omit<FeedbackItem, "id" | "createdAt">, projectId: string, userId: string) => Promise<string>;
9
+ export declare const updateFeedback: (feedbackId: string, updates: Partial<Omit<FeedbackItem, "id" | "createdAt">>) => Promise<void>;
10
+ export declare const deleteFeedback: (feedbackId: string) => Promise<void>;
11
+ export declare const subscribeFeedback: (projectId: string, callback: (feedback: FeedbackItem[]) => void) => (() => void);
@@ -0,0 +1,31 @@
1
+ import { UserInfo, UserRole } from '../types';
2
+ export interface UserProfile {
3
+ id: string;
4
+ name: string;
5
+ email: string;
6
+ role: UserRole;
7
+ avatar?: string;
8
+ createdAt: string;
9
+ updatedAt: string;
10
+ }
11
+ /**
12
+ * Create or update a user profile in Firestore
13
+ */
14
+ export declare const createOrUpdateUserProfile: (userId: string, email: string, name?: string, role?: UserRole) => Promise<UserProfile>;
15
+ /**
16
+ * Get a user profile from Firestore
17
+ */
18
+ export declare const getUserProfile: (userId: string) => Promise<UserProfile | null>;
19
+ /**
20
+ * Update a user's role (admin/developer only)
21
+ */
22
+ export declare const updateUserRole: (userId: string, newRole: UserRole) => Promise<void>;
23
+ /**
24
+ * Update a user's name
25
+ */
26
+ export declare const updateUserName: (userId: string, newName: string) => Promise<void>;
27
+ /**
28
+ * Check if a user can delete feedback
29
+ * Only the creator, developers, or admins can delete
30
+ */
31
+ export declare const canDeleteFeedback: (currentUser: UserInfo, feedbackCreatorId: string) => boolean;
@@ -0,0 +1 @@
1
+ export { useMarkupStore, default } from './useMarkupStore';
@@ -0,0 +1,13 @@
1
+ import type { MarkupStore } from '../types';
2
+ export declare const useMarkupStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<MarkupStore>, "persist"> & {
3
+ persist: {
4
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<MarkupStore, unknown>>) => void;
5
+ clearStorage: () => void;
6
+ rehydrate: () => Promise<void> | void;
7
+ hasHydrated: () => boolean;
8
+ onHydrate: (fn: (state: MarkupStore) => void) => () => void;
9
+ onFinishHydration: (fn: (state: MarkupStore) => void) => () => void;
10
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<MarkupStore, unknown>>;
11
+ };
12
+ }>;
13
+ export default useMarkupStore;
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-800:oklch(47% .157 37.304);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-800:oklch(47.6% .114 61.907);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-800:oklch(44.8% .119 151.328);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-800:oklch(42.4% .199 265.638);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-800:oklch(43.8% .218 303.724);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-8xl:6rem;--text-8xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--blur-md:12px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.-top-3{top:calc(var(--spacing)*-3)}.top-1\/2{top:50%}.top-3{top:calc(var(--spacing)*3)}.top-4{top:calc(var(--spacing)*4)}.top-16{top:calc(var(--spacing)*16)}.right-0{right:calc(var(--spacing)*0)}.right-3{right:calc(var(--spacing)*3)}.right-4{right:calc(var(--spacing)*4)}.bottom-4{bottom:calc(var(--spacing)*4)}.bottom-16{bottom:calc(var(--spacing)*16)}.-left-1{left:calc(var(--spacing)*-1)}.left-0{left:calc(var(--spacing)*0)}.left-3{left:calc(var(--spacing)*3)}.z-10{z-index:10}.z-\[99999\]{z-index:99999}.z-\[999999\]{z-index:999999}.z-\[1000000\]{z-index:1000000}.z-\[1000001\]{z-index:1000001}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing)*0)}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-6{margin-top:calc(var(--spacing)*6)}.mr-1{margin-right:calc(var(--spacing)*1)}.mb-1\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.ml-10{margin-left:calc(var(--spacing)*10)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-12{height:calc(var(--spacing)*12)}.h-\[24px\]{height:24px}.h-\[750px\]{height:750px}.h-fit{height:fit-content}.h-full{height:100%}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\[80px\]{min-height:80px}.min-h-\[100px\]{min-height:100px}.min-h-screen{min-height:100vh}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-12{width:calc(var(--spacing)*12)}.w-\[500px\]{width:500px}.w-full{width:100%}.w-px{width:1px}.max-w-4xl{max-width:var(--container-4xl)}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.min-w-\[24px\]{min-width:24px}.min-w-\[150px\]{min-width:150px}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-90{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-110{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x)var(--tw-scale-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-12{gap:calc(var(--spacing)*12)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-xl{border-top-left-radius:var(--radius-xl);border-top-right-radius:var(--radius-xl)}.rounded-l-2xl{border-top-left-radius:var(--radius-2xl);border-bottom-left-radius:var(--radius-2xl)}.rounded-l-xl{border-top-left-radius:var(--radius-xl);border-bottom-left-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-\[\#C2D1D9\]{border-color:#c2d1d9}.border-black{border-color:var(--color-black)}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-700{border-color:var(--color-gray-700)}.border-gray-900{border-color:var(--color-gray-900)}.border-green-200{border-color:var(--color-green-200)}.border-indigo-200{border-color:var(--color-indigo-200)}.border-red-200{border-color:var(--color-red-200)}.border-white{border-color:var(--color-white)}.border-white\/30{border-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.border-white\/30{border-color:color-mix(in oklab,var(--color-white)30%,transparent)}}.border-t-indigo-600{border-top-color:var(--color-indigo-600)}.border-t-white{border-top-color:var(--color-white)}.bg-\[\#C2D1D9\]{background-color:#c2d1d9}.bg-\[\#E6B6CF\]{background-color:#e6b6cf}.bg-black{background-color:var(--color-black)}.bg-black\/90{background-color:#000000e6}@supports (color:color-mix(in lab, red, red)){.bg-black\/90{background-color:color-mix(in oklab,var(--color-black)90%,transparent)}}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-300{background-color:var(--color-gray-300)}.bg-gray-500{background-color:var(--color-gray-500)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-500{background-color:var(--color-green-500)}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-orange-100{background-color:var(--color-orange-100)}.bg-purple-100{background-color:var(--color-purple-100)}.bg-purple-500{background-color:var(--color-purple-500)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.bg-white\/10{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-white\/95{background-color:#fffffff2}@supports (color:color-mix(in lab, red, red)){.bg-white\/95{background-color:color-mix(in oklab,var(--color-white)95%,transparent)}}.bg-yellow-100{background-color:var(--color-yellow-100)}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-t{--tw-gradient-position:to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-\[\#C2D1D9\]{--tw-gradient-from:#c2d1d9;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-black\/40{--tw-gradient-from:#0006}@supports (color:color-mix(in lab, red, red)){.from-black\/40{--tw-gradient-from:color-mix(in oklab,var(--color-black)40%,transparent)}}.from-black\/40{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-black\/60{--tw-gradient-from:#0009}@supports (color:color-mix(in lab, red, red)){.from-black\/60{--tw-gradient-from:color-mix(in oklab,var(--color-black)60%,transparent)}}.from-black\/60{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.via-black\/20{--tw-gradient-via:#0003}@supports (color:color-mix(in lab, red, red)){.via-black\/20{--tw-gradient-via:color-mix(in oklab,var(--color-black)20%,transparent)}}.via-black\/20{--tw-gradient-via-stops:var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-via)var(--tw-gradient-via-position),var(--tw-gradient-to)var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-purple-500{--tw-gradient-to:var(--color-purple-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.object-contain{object-fit:contain}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-2\.5{padding:calc(var(--spacing)*2.5)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-8{padding:calc(var(--spacing)*8)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.py-5{padding-block:calc(var(--spacing)*5)}.py-10{padding-block:calc(var(--spacing)*10)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-3{padding-top:calc(var(--spacing)*3)}.pt-6{padding-top:calc(var(--spacing)*6)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-3{padding-right:calc(var(--spacing)*3)}.pr-5{padding-right:calc(var(--spacing)*5)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pb-4{padding-bottom:calc(var(--spacing)*4)}.pl-9{padding-left:calc(var(--spacing)*9)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-8xl{font-size:var(--text-8xl);line-height:var(--tw-leading,var(--text-8xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.whitespace-pre-wrap{white-space:pre-wrap}.text-black{color:var(--color-black)}.text-blue-800{color:var(--color-blue-800)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-400{color:var(--color-green-400)}.text-green-800{color:var(--color-green-800)}.text-indigo-600{color:var(--color-indigo-600)}.text-orange-800{color:var(--color-orange-800)}.text-purple-800{color:var(--color-purple-800)}.text-red-400{color:var(--color-red-400)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-white{color:var(--color-white)}.text-yellow-400{color:var(--color-yellow-400)}.text-yellow-800{color:var(--color-yellow-800)}.uppercase{text-transform:uppercase}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[\#C2D1D9\]\/30{--tw-shadow-color:#c2d1d94d}@supports (color:color-mix(in lab, red, red)){.shadow-\[\#C2D1D9\]\/30{--tw-shadow-color:color-mix(in oklab,oklab(85.171% -.0125012 -.0152957/.3) var(--tw-shadow-alpha),transparent)}}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur-md{--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}@media (hover:hover){.group-hover\:scale-100:is(:where(.group):hover *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:translate-x-\[-8px\]:hover{--tw-translate-x:-8px;translate:var(--tw-translate-x)var(--tw-translate-y)}.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\:border-gray-300:hover{border-color:var(--color-gray-300)}.hover\:border-indigo-300:hover{border-color:var(--color-indigo-300)}.hover\:border-indigo-400:hover{border-color:var(--color-indigo-400)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-green-600:hover{background-color:var(--color-green-600)}.hover\:bg-indigo-50:hover{background-color:var(--color-indigo-50)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-100:hover{background-color:var(--color-red-100)}.hover\:bg-white:hover{background-color:var(--color-white)}.hover\:bg-white\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/20:hover{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:text-indigo-600:hover{color:var(--color-indigo-600)}.hover\:text-indigo-700:hover{color:var(--color-indigo-700)}.hover\:text-red-700:hover{color:var(--color-red-700)}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-sm:hover{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-gray-200:hover{--tw-shadow-color:oklch(92.8% .006 264.531)}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-gray-200:hover{--tw-shadow-color:color-mix(in oklab,var(--color-gray-200)var(--tw-shadow-alpha),transparent)}}}.focus\:border-\[\#C2D1D9\]:focus{border-color:#c2d1d9}.focus\:border-green-500:focus{border-color:var(--color-green-500)}.focus\:border-red-500:focus{border-color:var(--color-red-500)}.focus\:border-transparent:focus{border-color:#0000}.focus\:bg-white:focus{background-color:var(--color-white)}.focus\:shadow-lg:focus{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-4:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(4px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:shadow-\[\#C2D1D9\]\/10:focus{--tw-shadow-color:#c2d1d91a}@supports (color:color-mix(in lab, red, red)){.focus\:shadow-\[\#C2D1D9\]\/10:focus{--tw-shadow-color:color-mix(in oklab,oklab(85.171% -.0125012 -.0152957/.1) var(--tw-shadow-alpha),transparent)}}.focus\:shadow-green-500\/10:focus{--tw-shadow-color:#00c7581a}@supports (color:color-mix(in lab, red, red)){.focus\:shadow-green-500\/10:focus{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-green-500)10%,transparent)var(--tw-shadow-alpha),transparent)}}.focus\:shadow-red-500\/10:focus{--tw-shadow-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.focus\:shadow-red-500\/10:focus{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-red-500)10%,transparent)var(--tw-shadow-alpha),transparent)}}.focus\:ring-\[\#C2D1D9\]:focus{--tw-ring-color:#c2d1d9}.focus\:ring-indigo-200:focus{--tw-ring-color:var(--color-indigo-200)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}}.markup-widget{--primary-color:#6366f1}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}
@@ -0,0 +1,140 @@
1
+ export type FeedbackStatus = "open" | "in-progress" | "resolved" | "closed";
2
+ export type FeedbackType = "general" | "copy-amendment" | "bug" | "feature";
3
+ export type FeedbackPriority = "low" | "medium" | "high" | "critical";
4
+ export type AnnotationType = "arrow" | "rectangle" | "circle" | "text" | "highlight" | "freehand";
5
+ export type AnnotationTool = "pen" | "rectangle" | "circle" | "arrow" | "text";
6
+ export interface Annotation {
7
+ id: string;
8
+ type: AnnotationType | AnnotationTool;
9
+ x?: number;
10
+ y?: number;
11
+ startX?: number;
12
+ startY?: number;
13
+ width?: number;
14
+ height?: number;
15
+ endX?: number;
16
+ endY?: number;
17
+ text?: string;
18
+ color: string;
19
+ points?: {
20
+ x: number;
21
+ y: number;
22
+ }[];
23
+ path?: {
24
+ x: number;
25
+ y: number;
26
+ }[];
27
+ }
28
+ export interface PageMetadata {
29
+ url: string;
30
+ title: string;
31
+ screenWidth: number;
32
+ screenHeight: number;
33
+ devicePixelRatio: number;
34
+ userAgent: string;
35
+ timestamp: string;
36
+ }
37
+ export interface FeedbackItem {
38
+ id: string;
39
+ type?: FeedbackType;
40
+ title: string;
41
+ description?: string;
42
+ currentCopy?: string;
43
+ newCopy?: string;
44
+ screenshot?: string;
45
+ annotations: Annotation[];
46
+ status: FeedbackStatus;
47
+ priority: FeedbackPriority;
48
+ pageMetadata: PageMetadata;
49
+ elementSelector?: string;
50
+ createdAt: string;
51
+ updatedAt: string;
52
+ createdBy: UserInfo;
53
+ assignedTo?: UserInfo;
54
+ comments: Comment[];
55
+ tags: string[];
56
+ }
57
+ export type UserRole = "default" | "developer" | "admin";
58
+ export interface UserInfo {
59
+ id: string;
60
+ name: string;
61
+ email: string;
62
+ avatar?: string;
63
+ role: UserRole;
64
+ }
65
+ export interface Comment {
66
+ id: string;
67
+ text?: string;
68
+ content?: string;
69
+ createdAt: string;
70
+ createdBy: UserInfo;
71
+ }
72
+ export interface MarkupConfig {
73
+ projectId: string;
74
+ user?: Partial<UserInfo>;
75
+ apiEndpoint?: string;
76
+ apiKey?: string;
77
+ primaryColor?: string;
78
+ defaultOpen?: boolean;
79
+ shortcut?: string;
80
+ labels?: {
81
+ widgetButton?: string;
82
+ feedbackTitle?: string;
83
+ submitButton?: string;
84
+ cancelButton?: string;
85
+ };
86
+ onSubmit?: (feedback: FeedbackItem) => void | Promise<void>;
87
+ onStatusChange?: (feedbackId: string, status: FeedbackStatus) => void | Promise<void>;
88
+ onCommentAdd?: (feedbackId: string, comment: Comment) => void | Promise<void>;
89
+ onDelete?: (feedbackId: string) => void | Promise<void>;
90
+ allowStatusChange?: boolean;
91
+ features?: {
92
+ screenshot?: boolean;
93
+ annotations?: boolean;
94
+ console?: boolean;
95
+ network?: boolean;
96
+ localStorage?: boolean;
97
+ };
98
+ availableTags?: string[];
99
+ teamMembers?: UserInfo[];
100
+ }
101
+ export interface MarkupState {
102
+ isOpen: boolean;
103
+ isCapturing: boolean;
104
+ isAnnotating: boolean;
105
+ currentScreenshot: string | null;
106
+ annotations: Annotation[];
107
+ feedbackItems: FeedbackItem[];
108
+ selectedFeedback: FeedbackItem | null;
109
+ activeTab: "create" | "list" | "settings" | "auth";
110
+ activeTool: AnnotationType | null;
111
+ toolColor: string;
112
+ config: MarkupConfig;
113
+ currentUser: UserInfo | null;
114
+ isAuthenticated: boolean;
115
+ }
116
+ export interface MarkupActions {
117
+ setIsOpen: (isOpen: boolean) => void;
118
+ setIsCapturing: (isCapturing: boolean) => void;
119
+ setIsAnnotating: (isAnnotating: boolean) => void;
120
+ setCurrentScreenshot: (screenshot: string | null) => void;
121
+ addAnnotation: (annotation: Annotation) => void;
122
+ updateAnnotation: (id: string, updates: Partial<Annotation>) => void;
123
+ removeAnnotation: (id: string) => void;
124
+ clearAnnotations: () => void;
125
+ addFeedbackItem: (item: FeedbackItem) => void;
126
+ setFeedbackItems: (items: FeedbackItem[]) => void;
127
+ updateFeedback: (item: FeedbackItem) => void;
128
+ updateFeedbackItem: (id: string, updates: Partial<FeedbackItem>) => void;
129
+ removeFeedbackItem: (id: string) => void;
130
+ setSelectedFeedback: (feedback: FeedbackItem | null) => void;
131
+ setActiveTab: (tab: "create" | "list" | "settings" | "auth") => void;
132
+ setActiveTool: (tool: AnnotationType | null) => void;
133
+ setToolColor: (color: string) => void;
134
+ setConfig: (config: Partial<MarkupConfig>) => void;
135
+ addComment: (feedbackId: string, comment: Comment) => void;
136
+ setCurrentUser: (user: UserInfo | null) => void;
137
+ setIsAuthenticated: (isAuthenticated: boolean) => void;
138
+ reset: () => void;
139
+ }
140
+ export type MarkupStore = MarkupState & MarkupActions;
@@ -0,0 +1,22 @@
1
+ import type { FeedbackItem, MarkupConfig } from '../types';
2
+ export declare class MarkupAPI {
3
+ private baseUrl;
4
+ private apiKey;
5
+ private projectId;
6
+ constructor(config: MarkupConfig);
7
+ private request;
8
+ getFeedback(): Promise<FeedbackItem[]>;
9
+ createFeedback(feedback: FeedbackItem): Promise<FeedbackItem>;
10
+ updateFeedback(id: string, updates: Partial<FeedbackItem>): Promise<FeedbackItem>;
11
+ deleteFeedback(id: string): Promise<void>;
12
+ addComment(feedbackId: string, comment: {
13
+ text: string;
14
+ createdBy: {
15
+ id: string;
16
+ name: string;
17
+ email: string;
18
+ };
19
+ }): Promise<void>;
20
+ uploadScreenshot(dataUrl: string): Promise<string>;
21
+ }
22
+ export default MarkupAPI;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Automatically initialize Firebase from environment variables if not already initialized.
3
+ * This is called by widgets on mount to ensure Firebase is ready.
4
+ */
5
+ export declare const autoInitializeFirebase: () => boolean;
@@ -0,0 +1,5 @@
1
+ import { type ClassValue } from 'clsx';
2
+ /**
3
+ * Merge Tailwind classes with clsx
4
+ */
5
+ export declare function cn(...inputs: ClassValue[]): string;
@@ -0,0 +1,10 @@
1
+ import type { PageMetadata } from '../types';
2
+ export declare function captureScreenshot(): Promise<string>;
3
+ export declare function getPageMetadata(): PageMetadata;
4
+ export declare function getElementSelector(element: Element): string;
5
+ export declare function generateId(): string;
6
+ export declare function formatDate(dateString: string): string;
7
+ export declare function getStatusColor(status: string): string;
8
+ export declare function getPriorityColor(priority: string): string;
9
+ export declare function downloadScreenshot(dataUrl: string, filename?: string): void;
10
+ export declare function copyToClipboard(text: string): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export * from './helpers';
2
+ export { MarkupAPI } from './api';
3
+ export { cn } from './cn';
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@sirendesign/markup",
3
+ "version": "1.0.0",
4
+ "description": "A web markup and feedback tool for collecting visual feedback from clients and account managers",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.esm.js",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./styles.css": "./dist/styles.css"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build:css": "npx @tailwindcss/cli -i ./src/styles/markup.css -o ./dist/styles.css --minify",
21
+ "build:js": "rollup -c rollup.config.mjs",
22
+ "build": "npm run build:js && npm run build:css",
23
+ "watch:css": "npx @tailwindcss/cli -i ./src/styles/markup.css -o ./dist/styles.css --watch",
24
+ "watch:js": "rollup -c rollup.config.mjs -w",
25
+ "dev": "concurrently \"npm:watch:js\" \"npm:watch:css\"",
26
+ "test-app": "npm run build && cd test-app && npm run dev",
27
+ "prepublishOnly": "npm run build",
28
+ "lint": "eslint src --ext .ts,.tsx",
29
+ "type-check": "tsc --noEmit"
30
+ },
31
+ "keywords": [
32
+ "react",
33
+ "feedback",
34
+ "markup",
35
+ "annotation",
36
+ "screenshot",
37
+ "bug-reporting",
38
+ "marker",
39
+ "widget"
40
+ ],
41
+ "author": "",
42
+ "license": "MIT",
43
+ "peerDependencies": {
44
+ "react": ">=17.0.0",
45
+ "react-dom": ">=17.0.0",
46
+ "firebase": ">=11.0.0"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "firebase": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "devDependencies": {
54
+ "@rollup/plugin-commonjs": "^25.0.7",
55
+ "@rollup/plugin-node-resolve": "^15.2.3",
56
+ "@rollup/plugin-typescript": "^11.1.5",
57
+ "@types/html2canvas": "^1.0.0",
58
+ "@types/react": "^18.2.45",
59
+ "@types/react-dom": "^18.2.17",
60
+ "autoprefixer": "^10.4.23",
61
+ "concurrently": "^9.2.1",
62
+ "postcss": "^8.5.6",
63
+ "rollup": "^4.9.1",
64
+ "rollup-plugin-postcss": "^4.0.2",
65
+ "tailwindcss": "^4.1.18",
66
+ "tslib": "^2.8.1",
67
+ "typescript": "^5.3.3"
68
+ },
69
+ "dependencies": {
70
+ "clsx": "^2.1.0",
71
+ "html2canvas": "^1.4.1",
72
+ "tailwind-merge": "^2.2.0",
73
+ "zustand": "^4.4.7"
74
+ },
75
+ "optionalDependencies": {
76
+ "firebase": "^12.8.0"
77
+ }
78
+ }