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
+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
@@ -0,0 +1 @@
{"version":3,"file":"FilterButtons.d.ts","sourceRoot":"","sources":["../../src/lib/FilterButtons.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,UAAU,KAAK;IACb,OAAO,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC7C,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAiBD,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,2CAoBtD"}
@@ -0,0 +1,11 @@
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
interface ToggleButtonProps {
isActive: boolean;
icon?: IconDefinition;
activeIcon?: IconDefinition;
onClick: () => void;
className?: string;
}
export declare const ToggleButton: ({ isActive, icon, activeIcon, onClick, className, }: ToggleButtonProps) => import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=ToggleButton.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ToggleButton.d.ts","sourceRoot":"","sources":["../../src/lib/ToggleButton.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAInE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,YAAY,GAAI,qDAM1B,iBAAiB,4CAenB,CAAC"}
+16
View File
@@ -0,0 +1,16 @@
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
import { ButtonHTMLAttributes } from 'react';
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
icon?: IconDefinition;
iconClassName?: string;
iconFlip?: boolean;
htmlFor?: string;
variant?: "primary" | "secondary" | "action" | "destructive" | "ghost";
loading?: boolean;
as?: "button" | "link";
href?: string;
target?: string;
}
export declare const Button: ({ icon, iconClassName, children, className: propsClassName, htmlFor, variant: propsVariant, disabled, iconFlip, loading, as, href, target, ...rest }: ButtonProps) => import("react/jsx-runtime").JSX.Element;
export default Button;
//# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/lib/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAGnE,OAAO,EAAE,oBAAoB,EAAwB,MAAM,OAAO,CAAC;AAQnE,MAAM,WAAW,WAAY,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IAC1E,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,GAAG,OAAO,CAAC;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,MAAM,GAAI,sJAcpB,WAAW,4CAsHb,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-button",
"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,3 @@
export * from "./lib/button";
export * from "./lib/ToggleButton";
export * from "./lib/FilterButtons";
@@ -0,0 +1,43 @@
import { AssetFilterOption } from "@storyteller/common";
interface Props {
onClick: (button: AssetFilterOption) => void;
value: AssetFilterOption;
}
const FILTERS = [
{
text: "Featured",
option: AssetFilterOption.FEATURED,
},
{
text: "Mine",
option: AssetFilterOption.MINE,
},
{
text: "Bookmarked",
option: AssetFilterOption.BOOKMARKED,
},
];
export function FilterButtons({ onClick, value }: Props) {
return (
<div>
<div className="flex gap-2 overflow-x-auto overflow-y-hidden px-4">
{FILTERS.map((filter) => {
const isBookmarks = filter.option === AssetFilterOption.BOOKMARKED;
return (
<button
key={filter.option}
className={`filter-tab${value === filter.option ? " active" : ""}`}
disabled={isBookmarks}
onClick={() => onClick(filter.option)}
>
{filter.text}
</button>
);
})}
</div>
</div>
);
}
@@ -0,0 +1,34 @@
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { Button } from "./button";
import { twMerge } from "tailwind-merge";
interface ToggleButtonProps {
isActive: boolean;
icon?: IconDefinition;
activeIcon?: IconDefinition;
onClick: () => void;
className?: string;
}
export const ToggleButton = ({
isActive,
icon,
activeIcon,
onClick,
className,
}: ToggleButtonProps) => {
return (
<Button
className={twMerge(
"flex h-9 w-9 items-center border-2 border-transparent text-sm text-white backdrop-blur-lg transition-all",
isActive
? "border-white/20 bg-brand-primary/40 hover:border-white/30 hover:bg-brand-primary/40"
: "bg-[#5F5F68]/60 hover:bg-[#5F5F68]/90",
className
)}
variant="secondary"
icon={isActive && activeIcon ? activeIcon : icon}
onClick={onClick}
/>
);
};
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
import Button from './button';
describe('Button', () => {
it('should render successfully', () => {
const { baseElement } = render(<Button />);
expect(baseElement).toBeTruthy();
});
});
@@ -0,0 +1,158 @@
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { ButtonHTMLAttributes, AnchorHTMLAttributes } from "react";
import { faSpinnerThird } from "@fortawesome/pro-solid-svg-icons";
type AnchorProps = Omit<
AnchorHTMLAttributes<HTMLAnchorElement>,
keyof ButtonHTMLAttributes<HTMLButtonElement>
>;
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
icon?: IconDefinition;
iconClassName?: string;
iconFlip?: boolean;
htmlFor?: string;
variant?: "primary" | "secondary" | "action" | "destructive" | "ghost";
loading?: boolean;
as?: "button" | "link";
href?: string;
target?: string;
}
export const Button = ({
icon,
iconClassName,
children,
className: propsClassName,
htmlFor,
variant: propsVariant = "primary",
disabled,
iconFlip = false,
loading,
as = "button",
href,
target,
...rest
}: ButtonProps) => {
function getVariantClassNames(variant: string) {
switch (variant) {
case "secondary": {
return "bg-ui-controls text-base-fg border border-ui-controls-border hover:bg-ui-controls/80 focus-visible:outline-secondary";
}
case "action": {
return "bg-ui-controls text-base-fg border border-ui-controls-border hover:bg-ui-controls/80 focus-visible:outline-action";
}
case "destructive": {
return "bg-red hover:bg-red/90 text-white focus-visible:outline-red";
}
case "ghost": {
return "bg-transparent text-base-fg border border-ui-controls-border/70 hover:bg-ui-controls/30 focus-visible:outline-primary-600";
}
case "primary":
default: {
return "bg-primary hover:bg-primary-400 text-white focus-visible:outline-primary-600";
}
}
}
const disabledClass = twMerge(
disabled || loading ? "opacity-50 pointer-events-none" : ""
);
const className = twMerge(
"w-fit text-sm font-medium rounded-lg px-3 py-2 border border-transparent shadow-sm focus-visible:outline focus-visible:outline-0 focus-visible:outline-offset-0 transition-all duration-150 flex gap-2 items-center justify-center active:scale-95 transform",
getVariantClassNames(propsVariant),
propsClassName,
disabledClass
);
if (htmlFor) {
return (
<label className={className} htmlFor={htmlFor} style={rest.style}>
{loading && !iconFlip ? (
<FontAwesomeIcon icon={faSpinnerThird} className="animate-spin" />
) : (
<>
{icon && !iconFlip ? (
<FontAwesomeIcon icon={icon} className={iconClassName} />
) : null}
</>
)}
{children}
{loading && iconFlip ? (
<FontAwesomeIcon icon={faSpinnerThird} className="animate-spin" />
) : (
<>
{icon && iconFlip ? (
<FontAwesomeIcon icon={icon} className={iconClassName} />
) : null}
</>
)}
</label>
);
}
if (as === "link" && href) {
return (
<a
href={href}
className={className}
style={rest.style}
{...(rest as unknown as AnchorProps)}
target={target}
>
{loading && !iconFlip ? (
<FontAwesomeIcon icon={faSpinnerThird} className="animate-spin" />
) : (
<>
{icon && !iconFlip ? (
<FontAwesomeIcon icon={icon} className={iconClassName} />
) : null}
</>
)}
{children}
{loading && iconFlip ? (
<FontAwesomeIcon icon={faSpinnerThird} className="animate-spin" />
) : (
<>
{icon && iconFlip ? (
<FontAwesomeIcon icon={icon} className={iconClassName} />
) : null}
</>
)}
</a>
);
}
return (
<button
className={className}
disabled={disabled || loading}
{...{ ...rest, htmlFor }}
>
{loading && !iconFlip ? (
<FontAwesomeIcon icon={faSpinnerThird} className="animate-spin" />
) : (
<>
{icon && !iconFlip ? (
<FontAwesomeIcon icon={icon} className={iconClassName} />
) : null}
</>
)}
{children}
{loading && iconFlip ? (
<FontAwesomeIcon icon={faSpinnerThird} className="animate-spin" />
) : (
<>
{icon && iconFlip ? (
<FontAwesomeIcon icon={icon} className={iconClassName} />
) : null}
</>
)}
</button>
);
};
export default Button;
@@ -0,0 +1,16 @@
{
"files": [],
"include": [],
"references": [
{
"path": "../../common"
},
{
"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": "../../common/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',
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',
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,
}
},
}));