mirror repo (WIP)

Need to remove secrets before entire repo can be made public.
This commit is contained in:
Brandon Thomas
2025-09-18 22:55:03 -04:00
commit 0daf83dba9
8735 changed files with 2963896 additions and 0 deletions
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-action-reminder-modal
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-action-reminder-modal` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,3 @@
export * from './lib/action-reminder-modal-signals';
export * from './lib/action-reminder-modal';
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC"}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,24 @@
import { ReactNode } from 'react';
import { ReminderType } from '@storyteller/ui-action-reminder-modal';
import { IconDefinition } from '@fortawesome/pro-solid-svg-icons';
export interface ShowActionReminderOptions {
reminderType: ReminderType;
onPrimaryAction: () => void;
title?: string;
message?: ReactNode;
primaryActionText?: string;
secondaryActionText?: string;
onSecondaryAction?: () => void;
isLoading?: boolean;
openAiLogo?: string;
primaryActionIcon?: IconDefinition;
primaryActionBtnClassName?: string;
}
interface ActionReminderModalFullProps extends ShowActionReminderOptions {
onClose: () => void;
}
export declare const isActionReminderOpen: import('@preact/signals-core').Signal<boolean>;
export declare const actionReminderProps: import('@preact/signals-core').Signal<ActionReminderModalFullProps | null>;
export declare function showActionReminder(options: ShowActionReminderOptions): void;
export {};
//# sourceMappingURL=action-reminder-modal-signals.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"action-reminder-modal-signals.d.ts","sourceRoot":"","sources":["../../src/lib/action-reminder-modal-signals.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,cAAc,CAAC;IACnC,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,UAAU,4BAA6B,SAAQ,yBAAyB;IACtE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,oBAAoB,gDAAgB,CAAC;AAClD,eAAO,MAAM,mBAAmB,4EAE/B,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,IAAI,CAQ3E"}
@@ -0,0 +1,24 @@
import { ReactNode } from 'react';
import { IconDefinition } from '@fortawesome/pro-solid-svg-icons';
export type ReminderType = "default" | "soraLogin" | "artcraftLogin";
interface ActionReminderModalProps {
isOpen: boolean;
onClose: () => void;
reminderType?: ReminderType;
onPrimaryAction: () => void;
title?: string;
hideTitle?: boolean;
message?: ReactNode;
children?: ReactNode;
primaryActionText?: string;
secondaryActionText?: string;
onSecondaryAction?: () => void;
isLoading?: boolean;
openAiLogo?: string;
modalClassName?: string;
primaryActionIcon?: IconDefinition;
primaryActionBtnClassName?: string;
}
export declare function ActionReminderModal({ isOpen, onClose, reminderType, onPrimaryAction, title: customTitle, hideTitle, message: customMessage, children: customChildren, primaryActionText: customPrimaryActionText, secondaryActionText: customSecondaryActionText, onSecondaryAction, isLoading, modalClassName: customModalClassName, primaryActionIcon: customPrimaryActionIcon, primaryActionBtnClassName: customPrimaryActionBtnClassName, }: ActionReminderModalProps): import("react/jsx-runtime").JSX.Element;
export default ActionReminderModal;
//# sourceMappingURL=action-reminder-modal.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"action-reminder-modal.d.ts","sourceRoot":"","sources":["../../src/lib/action-reminder-modal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAGlE,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC;AAErE,UAAU,wBAAwB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,cAAc,CAAC;IACnC,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,OAAO,EACP,YAAwB,EACxB,eAAe,EACf,KAAK,EAAE,WAAW,EAClB,SAAiB,EACjB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,cAAc,EACxB,iBAAiB,EAAE,uBAAuB,EAC1C,mBAAmB,EAAE,yBAAyB,EAC9C,iBAAiB,EACjB,SAAiB,EACjB,cAAc,EAAE,oBAAyB,EACzC,iBAAiB,EAAE,uBAA0C,EAC7D,yBAAyB,EAAE,+BAAoC,GAChE,EAAE,wBAAwB,2CAyG1B;AAED,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-action-reminder-modal",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from "./lib/action-reminder-modal-signals";
export * from "./lib/action-reminder-modal";
@@ -0,0 +1,51 @@
// frontend/apps/editor3d/app/src/signals/actionReminderSignals.ts
import { signal } from "@preact/signals-react";
import { ReactNode } from "react";
import { ReminderType } from "@storyteller/ui-action-reminder-modal";
import { IconDefinition } from "@fortawesome/pro-solid-svg-icons";
export interface ShowActionReminderOptions {
reminderType: ReminderType;
onPrimaryAction: () => void;
title?: string;
message?: ReactNode;
primaryActionText?: string;
secondaryActionText?: string;
onSecondaryAction?: () => void;
isLoading?: boolean;
openAiLogo?: string;
primaryActionIcon?: IconDefinition;
primaryActionBtnClassName?: string;
}
interface ActionReminderModalFullProps extends ShowActionReminderOptions {
onClose: () => void;
}
export const isActionReminderOpen = signal(false);
export const actionReminderProps = signal<ActionReminderModalFullProps | null>(
null
);
export function showActionReminder(options: ShowActionReminderOptions): void {
actionReminderProps.value = {
...options,
onClose: () => {
isActionReminderOpen.value = false;
},
};
isActionReminderOpen.value = true;
}
// Example of how to trigger it - BFlat:
// import { showGlobalActionReminder } from "@storyteller/ui-action-reminder-modal";
// import openAiLogo from 'path/to/logo.svg';
//
// function someAction() {
// showActionReminder({
// reminderType: 'soraLogin',
// onPrimaryAction: () => console.log('Login with Sora!'),
// openAiLogo: openAiLogo,
// title: 'Sora Login Needed'
// });
// }
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
import ActionReminderModal from './action-reminder-modal';
describe('ActionReminderModal', () => {
it('should render successfully', () => {
const { baseElement } = render(<ActionReminderModal />);
expect(baseElement).toBeTruthy();
});
});
@@ -0,0 +1,152 @@
import { Button } from "@storyteller/ui-button";
import { Modal } from "@storyteller/ui-modal";
import { ReactNode } from "react";
import { faRightToBracket } from "@fortawesome/pro-solid-svg-icons";
import { IconDefinition } from "@fortawesome/pro-solid-svg-icons";
import { twMerge } from "tailwind-merge";
export type ReminderType = "default" | "soraLogin" | "artcraftLogin";
interface ActionReminderModalProps {
isOpen: boolean;
onClose: () => void;
reminderType?: ReminderType;
onPrimaryAction: () => void;
title?: string;
hideTitle?: boolean;
message?: ReactNode;
children?: ReactNode;
primaryActionText?: string;
secondaryActionText?: string;
onSecondaryAction?: () => void;
isLoading?: boolean;
openAiLogo?: string;
modalClassName?: string;
primaryActionIcon?: IconDefinition;
primaryActionBtnClassName?: string;
}
export function ActionReminderModal({
isOpen,
onClose,
reminderType = "default",
onPrimaryAction,
title: customTitle,
hideTitle = false,
message: customMessage,
children: customChildren,
primaryActionText: customPrimaryActionText,
secondaryActionText: customSecondaryActionText,
onSecondaryAction,
isLoading = false,
modalClassName: customModalClassName = "",
primaryActionIcon: customPrimaryActionIcon = faRightToBracket,
primaryActionBtnClassName: customPrimaryActionBtnClassName = "",
}: ActionReminderModalProps) {
let titleText: string | undefined;
let messageContent: ReactNode;
let primaryActionBtnText: string;
let primaryActionIcon = faRightToBracket;
let primaryActionBtnClassName = "";
if (!hideTitle) {
switch (reminderType) {
case "soraLogin":
titleText = customTitle || "Link Your OpenAI Sora Account";
break;
case "artcraftLogin":
titleText = customTitle || "Login to ArtCraft";
break;
default:
titleText = customTitle || "Action Required";
break;
}
} else {
titleText = undefined;
}
switch (reminderType) {
case "soraLogin":
titleText = customTitle || "Link Your OpenAI Account";
messageContent = customMessage || (
<p>
To use this feature, please connect your OpenAI account. This allows
us to leverage your existing subscription.
</p>
);
primaryActionBtnText = customPrimaryActionText || "Login with OpenAI";
primaryActionIcon = customPrimaryActionIcon || faRightToBracket;
primaryActionBtnClassName = customPrimaryActionBtnClassName || "";
break;
case "artcraftLogin":
messageContent = customMessage || (
<p className="text-sm text-white/70">
Please log in or sign up to ArtCraft to proceed. This will allow you
to save your work and access all features.
</p>
);
primaryActionBtnText = customPrimaryActionText || "Login / Sign Up";
primaryActionIcon = customPrimaryActionIcon || faRightToBracket;
primaryActionBtnClassName = customPrimaryActionBtnClassName || "";
break;
default:
messageContent = customMessage || (
<p className="text-sm text-white/70">
Please complete the required action.
</p>
);
primaryActionBtnText = customPrimaryActionText || "Proceed";
primaryActionIcon = customPrimaryActionIcon || faRightToBracket;
primaryActionBtnClassName = customPrimaryActionBtnClassName || "";
break;
}
const effectiveSecondaryAction = onSecondaryAction || onClose;
const effectiveSecondaryActionText = customSecondaryActionText || "Cancel";
let modalSpecificClasses = "";
const finalModalClassName =
`${customModalClassName} ${modalSpecificClasses}`.trim();
return (
<Modal
isOpen={isOpen}
onClose={onClose}
title={titleText}
className={finalModalClassName}
>
<div>
{customChildren ? (
<div className="space-y-4">{customChildren}</div>
) : (
<div className="space-y-4">{messageContent}</div>
)}
<div className="mt-6 flex flex-col sm:flex-row-reverse gap-3">
<Button
onClick={onPrimaryAction}
loading={isLoading}
disabled={isLoading}
icon={primaryActionIcon}
className={twMerge("w-full sm:w-auto", primaryActionBtnClassName)}
>
{primaryActionBtnText}
</Button>
{(onSecondaryAction || customSecondaryActionText) && (
<Button
variant="secondary"
onClick={effectiveSecondaryAction}
disabled={isLoading}
className="w-full sm:w-auto"
>
{effectiveSecondaryActionText}
</Button>
)}
</div>
</div>
</Modal>
);
}
export default ActionReminderModal;
@@ -0,0 +1,19 @@
{
"files": [],
"include": [],
"references": [
{
"path": "../modal"
},
{
"path": "../button"
},
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,53 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
],
"references": [
{
"path": "../modal/tsconfig.lib.json"
},
{
"path": "../button/tsconfig.lib.json"
}
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/action-reminder-modal',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-action-reminder-modal',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
+12
View File
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
+7
View File
@@ -0,0 +1,7 @@
# @storyteller/ui-badge
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-badge` to execute the unit tests via [Vitest](https://vitest.dev/).
+2
View File
@@ -0,0 +1,2 @@
export * from './lib/badge';
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAC"}
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
interface BadgeProps {
label: string;
color?: string;
className?: string;
}
export declare const Badge: ({ label, className }: BadgeProps) => import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=badge.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../src/lib/badge.tsx"],"names":[],"mappings":"AAEA,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,KAAK,GAAI,sBAAsB,UAAU,4CAWrD,CAAC"}
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-badge",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/badge';
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
import Badge from './badge';
describe('Badge', () => {
it('should render successfully', () => {
const { baseElement } = render(<Badge />);
expect(baseElement).toBeTruthy();
});
});
@@ -0,0 +1,20 @@
import { twMerge } from "tailwind-merge";
interface BadgeProps {
label: string;
color?: string;
className?: string;
}
export const Badge = ({ label, className }: BadgeProps) => {
return (
<div
className={twMerge(
"rounded-[6px] bg-ui-controls/45 px-[4px] py-[1px] text-[10px] shadow-sm",
className
)}
>
{label}
</div>
);
};
@@ -0,0 +1,13 @@
{
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,45 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/badge',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-badge',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-button-dropdown
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-button-dropdown` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,2 @@
export * from './lib/button-dropdown';
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAC"}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,35 @@
import { ButtonHTMLAttributes } from 'react';
import { IconDefinition } from '@fortawesome/pro-solid-svg-icons';
import { ButtonProps } from '@storyteller/ui-button';
type UnionedButtonProps = {
label?: string;
} & ButtonProps;
interface ButtonDropdownProps extends ButtonHTMLAttributes<HTMLButtonElement> {
label: string;
icon?: IconDefinition;
align?: "left" | "right";
showSelected?: boolean;
options: Array<{
label: string;
className?: string;
icon?: IconDefinition;
selected?: boolean;
description?: string;
onClick?: () => void;
disabled?: boolean;
divider?: boolean;
onDialogOpen?: () => void;
dialogProps?: {
title: string;
content: React.ReactNode;
className?: string;
confirmButtonProps?: UnionedButtonProps;
closeButtonProps?: UnionedButtonProps;
showClose?: boolean;
onClose?: () => void;
};
}>;
}
export declare const ButtonDropdown: ({ className, label, options, icon, align, showSelected, }: ButtonDropdownProps) => import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=button-dropdown.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"button-dropdown.d.ts","sourceRoot":"","sources":["../../src/lib/button-dropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAsB,MAAM,OAAO,CAAC;AAEjE,OAAO,EACL,cAAc,EAEf,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EAAU,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG7D,KAAK,kBAAkB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAAC;AAE3D,UAAU,mBAAoB,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,cAAc,CAAC;QACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;QAC1B,WAAW,CAAC,EAAE;YACZ,KAAK,EAAE,MAAM,CAAC;YACd,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;YACzB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;YACxC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;YACtC,SAAS,CAAC,EAAE,OAAO,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;SACtB,CAAC;KACH,CAAC,CAAC;CACJ;AAED,eAAO,MAAM,cAAc,GAAI,2DAO5B,mBAAmB,4CAqKrB,CAAC"}
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-button-dropdown",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/button-dropdown';
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
import ButtonDropdown from './button-dropdown';
describe('ButtonDropdown', () => {
it('should render successfully', () => {
const { baseElement } = render(<ButtonDropdown />);
expect(baseElement).toBeTruthy();
});
});
@@ -0,0 +1,213 @@
import { ButtonHTMLAttributes, Fragment, useState } from "react";
import { Menu, Transition } from "@headlessui/react";
import {
IconDefinition,
faChevronDown,
} from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Modal } from "@storyteller/ui-modal";
import { Button, ButtonProps } from "@storyteller/ui-button";
import { twMerge } from "tailwind-merge";
type UnionedButtonProps = { label?: string } & ButtonProps;
interface ButtonDropdownProps extends ButtonHTMLAttributes<HTMLButtonElement> {
label: string;
icon?: IconDefinition;
align?: "left" | "right";
showSelected?: boolean;
options: Array<{
label: string;
className?: string;
icon?: IconDefinition;
selected?: boolean;
description?: string;
onClick?: () => void;
disabled?: boolean;
divider?: boolean;
onDialogOpen?: () => void;
dialogProps?: {
title: string;
content: React.ReactNode;
className?: string;
confirmButtonProps?: UnionedButtonProps;
closeButtonProps?: UnionedButtonProps;
showClose?: boolean;
onClose?: () => void;
};
}>;
}
export const ButtonDropdown = ({
className,
label,
options,
icon,
align = "left",
showSelected,
}: ButtonDropdownProps) => {
const [isOpen, setIsOpen] = useState(false);
const [selectedOptionIndex, setSelectedOptionIndex] = useState<number | null>(
null
);
const closeModal = () => {
setIsOpen(false);
options[selectedOptionIndex!].dialogProps?.onClose?.();
};
const handleOptionClick = (index: number) => {
const option = options[index];
if (option.onClick) {
option.onClick();
}
if (option.onDialogOpen) {
option.onDialogOpen();
}
if (option.dialogProps) {
setSelectedOptionIndex(index);
setIsOpen(true);
}
};
const currentDialogProps =
selectedOptionIndex !== null
? options[selectedOptionIndex].dialogProps
: null;
return (
<div className="relative">
<Menu as="div" className="inline-block text-left">
<Menu.Button as="div">
<Button
className={className}
icon={faChevronDown}
iconFlip={true}
variant="secondary"
>
{icon ? <FontAwesomeIcon icon={icon} /> : null}
{label}
</Button>
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
static
className={twMerge(
"absolute z-20 mt-1 w-max divide-y divide-gray-100 overflow-hidden rounded-lg bg-brand-secondary py-1.5 shadow-xl focus:outline-none",
align === "left" ? "left-0" : "right-0"
)}
>
<div>
{options.map((option, index) => (
<Fragment key={index}>
{option.divider && (
<div className="my-1.5 border-t border-ui-divider" />
)}
<Menu.Item>
{({ active }) => (
<button
disabled={option.disabled}
className={twMerge(
"duration-50 bg-brand-secondary font-medium text-white transition-all",
active ? "bg-brand-secondary-800" : "",
option.disabled
? "pointer-events-none opacity-40"
: "",
"group flex w-full items-center py-1.5 pl-7 pr-4 text-sm",
option.className
)}
onClick={() => handleOptionClick(index)}
>
<div className="flex w-full items-center">
{option.icon && (
<FontAwesomeIcon
icon={option.icon}
className="mr-2"
/>
)}
<div className="grow text-start">{option.label}</div>
<div className="ml-10 font-normal text-white/75">
{option.description && option.description}
</div>
{showSelected && (
<>
{option.selected ? (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
className="ml-3 flex h-5"
>
<path
opacity="1"
d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c-9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"
fill="#FC6B68"
/>
<path
d="M369 175c-9.4 9.4-9.4 24.6 0 33.9L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c-9.4-9.4 24.6-9.4 33.9 0z"
fill="#FFFFFF"
/>
</svg>
) : (
<div className="w-8" />
)}
</>
)}
</div>
</button>
)}
</Menu.Item>
</Fragment>
))}
</div>
</Menu.Items>
</Transition>
</Menu>
{currentDialogProps && (
<Modal
title={currentDialogProps.title}
isOpen={isOpen}
onClose={closeModal}
className={currentDialogProps.className}
>
{currentDialogProps.content}
<div className="mt-6 flex justify-end gap-2">
{currentDialogProps.showClose !== false &&
currentDialogProps.closeButtonProps && (
<Button
variant="secondary"
{...currentDialogProps.closeButtonProps}
onClick={closeModal}
>
{currentDialogProps.closeButtonProps.label}
</Button>
)}
{currentDialogProps.confirmButtonProps && (
<Button
{...currentDialogProps.confirmButtonProps}
onClick={(e) => {
if (currentDialogProps.confirmButtonProps?.onClick) {
currentDialogProps.confirmButtonProps?.onClick(e);
}
closeModal();
}}
>
{currentDialogProps.confirmButtonProps.label || "Confirm"}
</Button>
)}
</div>
</Modal>
)}
</div>
);
};
@@ -0,0 +1,19 @@
{
"files": [],
"include": [],
"references": [
{
"path": "../button"
},
{
"path": "../modal"
},
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,53 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
],
"references": [
{
"path": "../button/tsconfig.lib.json"
},
{
"path": "../modal/tsconfig.lib.json"
}
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/button-dropdown',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-button-dropdown',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-button-icon-select
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-button-icon-select` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,2 @@
export * from './lib/button-icon-select';
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,0BAA0B,CAAC"}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,15 @@
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
interface Option {
value: string;
icon: IconDefinition;
text?: string;
tooltip?: string;
}
interface ButtonIconSelectProps {
options: Option[];
onOptionChange?: (value: string) => void;
selectedOption?: string;
}
export declare function ButtonIconSelect({ options, onOptionChange, selectedOption, }: ButtonIconSelectProps): import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=button-icon-select.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"button-icon-select.d.ts","sourceRoot":"","sources":["../../src/lib/button-icon-select.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAKnE,UAAU,MAAM;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,cAAc,EACd,cAAc,GACf,EAAE,qBAAqB,2CAgEvB"}
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-button-icon-select",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/button-icon-select';
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
import ButtonIconSelect from './button-icon-select';
describe('ButtonIconSelect', () => {
it('should render successfully', () => {
const { baseElement } = render(<ButtonIconSelect />);
expect(baseElement).toBeTruthy();
});
});
@@ -0,0 +1,88 @@
import { useState, useEffect } from "react";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { Tooltip } from "@storyteller/ui-tooltip";
interface Option {
value: string;
icon: IconDefinition;
text?: string;
tooltip?: string;
}
interface ButtonIconSelectProps {
options: Option[];
onOptionChange?: (value: string) => void;
selectedOption?: string;
}
export function ButtonIconSelect({
options,
onOptionChange,
selectedOption,
}: ButtonIconSelectProps) {
const [internalSelectedOption, setInternalSelectedOption] = useState<string>(
selectedOption || options[0].value
);
useEffect(() => {
setInternalSelectedOption(selectedOption || options[0].value);
}, [selectedOption, options]);
const handleOptionChange = (value: string) => {
setInternalSelectedOption(value);
if (onOptionChange) {
onOptionChange(value);
}
};
return (
<div className="flex space-x-1">
{options.map(({ value, icon, text, tooltip }) =>
tooltip ? (
<Tooltip
key={value}
content={tooltip}
position="bottom"
delay={300}
closeOnClick
>
<button
className={twMerge(
"flex h-9 items-center justify-center rounded-lg border text-sm outline-none transition-all duration-150 focus:outline-none",
text ? "h-auto w-auto gap-2 px-3 py-1.5" : "w-9",
internalSelectedOption === value
? "border-brand-primary bg-brand-primary/20"
: "border-transparent hover:bg-ui-panel/[0.4]"
)}
onClick={() => handleOptionChange(value)}
>
<FontAwesomeIcon icon={icon} />
{text && (
<span className="text-nowrap text-sm font-medium">{text}</span>
)}
</button>
</Tooltip>
) : (
<button
key={value}
className={twMerge(
`flex h-9 items-center justify-center rounded-lg border text-sm transition-all duration-150`,
text ? "h-auto w-auto gap-2 px-3 py-1.5" : "w-9",
internalSelectedOption === value
? "border-brand-primary bg-brand-primary/20"
: "border-transparent hover:bg-ui-panel/[0.4]"
)}
onClick={() => handleOptionChange(value)}
>
<FontAwesomeIcon icon={icon} />
{text && (
<span className="text-nowrap text-sm font-medium">{text}</span>
)}
</button>
)
)}
</div>
);
}
@@ -0,0 +1,16 @@
{
"files": [],
"include": [],
"references": [
{
"path": "../tooltip"
},
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,50 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
],
"references": [
{
"path": "../tooltip/tsconfig.lib.json"
}
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/button-icon-select',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-button-icon-select',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-button-icon
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-button-icon` to execute the unit tests via [Vitest](https://vitest.dev/).
+2
View File
@@ -0,0 +1,2 @@
export * from './lib/button-icon';
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAC"}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
import { FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
interface ButtonIconProps extends FontAwesomeIconProps {
icon: IconDefinition;
onClick: () => void;
className?: string;
bgFill?: boolean;
disabled?: boolean;
}
export declare const ButtonIcon: ({ icon, size, onClick, className: propsClassName, bgFill, disabled, ...rest }: ButtonIconProps) => import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=button-icon.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"button-icon.d.ts","sourceRoot":"","sources":["../../src/lib/button-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,EACrB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,UAAU,eAAgB,SAAQ,oBAAoB;IACpD,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,GAAI,+EAQxB,eAAe,4CAejB,CAAC"}
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-button-icon",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/button-icon';
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
import ButtonIcon from './button-icon';
describe('ButtonIcon', () => {
it('should render successfully', () => {
const { baseElement } = render(<ButtonIcon />);
expect(baseElement).toBeTruthy();
});
});
@@ -0,0 +1,39 @@
import {
FontAwesomeIcon,
FontAwesomeIconProps,
} from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
interface ButtonIconProps extends FontAwesomeIconProps {
icon: IconDefinition;
onClick: () => void;
className?: string;
bgFill?: boolean;
disabled?: boolean;
}
export const ButtonIcon = ({
icon,
size,
onClick,
className: propsClassName,
bgFill = false,
disabled,
...rest
}: ButtonIconProps) => {
const className = twMerge(
"box-content flex h-8 w-8 items-center justify-center rounded-lg transition-all duration-150",
bgFill
? "bg-ui-controls-button hover:bg-ui-controls-button/[0.75]"
: "bg-transparent hover:bg-ui-panel/[0.4]",
disabled && "opacity-50 hover:bg-transparent",
propsClassName
);
return (
<button className={className} onClick={onClick} disabled={disabled}>
<FontAwesomeIcon icon={icon} size={size} {...rest} />
</button>
);
};
@@ -0,0 +1,13 @@
{
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,45 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/button-icon',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-button-icon',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-button-link
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-button-link` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-button-link",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/button-link';
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
// import ButtonLink from './button-link';
// describe('ButtonLink', () => {
// it('should render successfully', () => {
// const { baseElement } = render(<ButtonLink />);
// expect(baseElement).toBeTruthy();
// });
// });
@@ -0,0 +1,44 @@
import { Link, LinkProps } from "react-router-dom";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
interface LinkButtonProps extends LinkProps {
icon?: IconDefinition;
variant?: "primary" | "secondary";
}
export const ButtonLink = ({
icon,
children,
className: propsClassName,
variant = "primary",
...rest
}: LinkButtonProps) => {
//TODO: Duplicated from Button.tsx
function getVariantClassNames(variant: string) {
switch (variant) {
case "secondary": {
return "bg-brand-secondary hover:bg-brand-secondary-600 text-white focus-visible:outline-brand-secondary";
}
case "primary":
default: {
return "bg-brand-primary hover:bg-brand-primary-400 text-white focus-visible:outline-brand-primary-600";
}
}
}
const baseClassName =
"text-sm font-medium whitespace-nowrap rounded-lg px-3 py-2 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 transition-all duration-150";
const variantClassNames = getVariantClassNames(variant);
const className = twMerge(baseClassName, variantClassNames, propsClassName);
// END TODO
return (
<Link {...rest}>
<button className={className}>
{icon && <FontAwesomeIcon className="mr-2" icon={icon} size="sm" />}
{children}
</button>
</Link>
);
};
@@ -0,0 +1,13 @@
{
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,45 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/button-link',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-button-link',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
+12
View File
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-button
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-button` to execute the unit tests via [Vitest](https://vitest.dev/).
+4
View File
@@ -0,0 +1,4 @@
export * from './lib/button';
export * from './lib/ToggleButton';
export * from './lib/FilterButtons';
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC"}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
import { AssetFilterOption } from '@storyteller/common';
interface Props {
onClick: (button: AssetFilterOption) => void;
value: AssetFilterOption;
}
export declare function FilterButtons({ onClick, value }: Props): import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=FilterButtons.d.ts.map

Some files were not shown because too many files have changed in this diff Show More