diff --git a/frontend/libs/components/select/src/lib/select.tsx b/frontend/libs/components/select/src/lib/select.tsx index eeca266c05..0525836efb 100644 --- a/frontend/libs/components/select/src/lib/select.tsx +++ b/frontend/libs/components/select/src/lib/select.tsx @@ -17,6 +17,7 @@ interface ListDropdownProps { placeholder?: string; value?: SelectValue; id?: string; + className?: string; } export const Select = ({ @@ -25,13 +26,14 @@ export const Select = ({ placeholder, value, id, + className, }: ListDropdownProps) => { const selectedOption = options.find( (option: SelectOption) => option.value === value ) || { label: placeholder || "", value: "" }; return ( -
+
{({ open }) => ( <> diff --git a/frontend/libs/components/settings-modal/src/lib/panes/AudioSettingsPane.tsx b/frontend/libs/components/settings-modal/src/lib/panes/AudioSettingsPane.tsx index d44f0529e5..58b3cfeace 100644 --- a/frontend/libs/components/settings-modal/src/lib/panes/AudioSettingsPane.tsx +++ b/frontend/libs/components/settings-modal/src/lib/panes/AudioSettingsPane.tsx @@ -1,10 +1,15 @@ import { useEffect, useState } from "react"; import { SoundRegistry } from "@storyteller/soundboard"; import { Button } from "@storyteller/ui-button"; -import { Input } from "@storyteller/ui-input"; -import { AppPreferencesPayload, GetAppPreferences } from "@storyteller/tauri-api"; +import { faPlay } from "@fortawesome/pro-solid-svg-icons"; +import { + AppPreferencesPayload, + GetAppPreferences, +} from "@storyteller/tauri-api"; import { PreferenceName, UpdateAppPreferences } from "@storyteller/tauri-api"; import { Select, SelectValue } from "@storyteller/ui-select"; +import { Switch } from "@storyteller/ui-switch"; +import { Label } from "@storyteller/ui-label"; // TODO: This is maintained in two places. Here and InstallSounds. const SOUND_OPTIONS = [ @@ -16,22 +21,22 @@ const SOUND_OPTIONS = [ { value: "crumble", label: "Crumble" }, ]; -interface AudioSettingsPaneProps { -} +interface AudioSettingsPaneProps {} export const AudioSettingsPane = (args: AudioSettingsPaneProps) => { - const [preferences, setPreferences] = useState(undefined); + const [preferences, setPreferences] = useState< + AppPreferencesPayload | undefined + >(undefined); useEffect(() => { const fetchData = async () => { const prefs = await GetAppPreferences(); - console.log("prefs", prefs) + console.log("prefs", prefs); setPreferences(prefs.preferences); - } + }; fetchData(); }, []); - const playSounds = preferences?.play_sounds || false; const successSound = orNone(preferences?.generation_success_sound); @@ -40,138 +45,129 @@ export const AudioSettingsPane = (args: AudioSettingsPaneProps) => { const reloadPreferences = async () => { const prefs = await GetAppPreferences(); - console.log("prefs", prefs) + console.log("prefs", prefs); setPreferences(prefs.preferences); - } + }; const setPlaySounds = async (checked: boolean) => { //const value = checked ? "true" : "false"; await UpdateAppPreferences({ - preference: PreferenceName.PlaySounds, + preference: PreferenceName.PlaySounds, value: checked, }); await reloadPreferences(); - } + }; const setSuccessSound = async (val: string) => { let sendVal = val === "none" ? undefined : val; await UpdateAppPreferences({ - preference: PreferenceName.GenerationSuccessSound, + preference: PreferenceName.GenerationSuccessSound, value: sendVal, }); SoundRegistry.getInstance().playSound(val); await reloadPreferences(); - } + }; const setFailureSound = async (val: string) => { let sendVal = val === "none" ? undefined : val; await UpdateAppPreferences({ - preference: PreferenceName.GenerationFailureSound, + preference: PreferenceName.GenerationFailureSound, value: sendVal, }); SoundRegistry.getInstance().playSound(val); await reloadPreferences(); - } + }; const setEnqueueSound = async (val: string) => { let sendVal = val === "none" ? undefined : val; await UpdateAppPreferences({ - preference: PreferenceName.GenerationEnqueueSound, + preference: PreferenceName.GenerationEnqueueSound, value: sendVal, }); SoundRegistry.getInstance().playSound(val); await reloadPreferences(); - } + }; const playSound = (val?: string) => { if (val !== undefined && val !== "none") { SoundRegistry.getInstance().playSound(val); } - } + }; - return (<> -
-
- - setPlaySounds((e.target as any).checked)} - /> + return ( + <> +
+
+ + +
+ +
+ +
+ setFailureSound(val as string)} + options={SOUND_OPTIONS} + className="grow" + /> +
+
+ +
+ +
+ - setSuccessSound(val as string) - } - options={SOUND_OPTIONS} - /> - -
- -
- - - setEnqueueSound(val as string) - } - options={SOUND_OPTIONS} - /> - -
-
- ) -} - -const orNone = (val: string | undefined | null) : string => { +const orNone = (val: string | undefined | null): string => { if (!!!val) { return "none"; } return val; -} +}; diff --git a/frontend/libs/components/settings-modal/src/lib/panes/MiscSettingsPane.tsx b/frontend/libs/components/settings-modal/src/lib/panes/MiscSettingsPane.tsx index b9f54b5893..df9615f776 100644 --- a/frontend/libs/components/settings-modal/src/lib/panes/MiscSettingsPane.tsx +++ b/frontend/libs/components/settings-modal/src/lib/panes/MiscSettingsPane.tsx @@ -1,35 +1,47 @@ import { useEffect, useState } from "react"; import { Button } from "@storyteller/ui-button"; -import { AppPreferencesPayload, CustomDirectory, GetAppPreferences, SystemDirectory } from "@storyteller/tauri-api"; +import { + AppPreferencesPayload, + CustomDirectory, + GetAppPreferences, + SystemDirectory, +} from "@storyteller/tauri-api"; import { PreferenceName, UpdateAppPreferences } from "@storyteller/tauri-api"; -import { open } from '@tauri-apps/plugin-dialog'; +import { open } from "@tauri-apps/plugin-dialog"; +import { Label } from "@storyteller/ui-label"; -interface MiscSettingsPaneProps { -} +interface MiscSettingsPaneProps {} export const MiscSettingsPane = (args: MiscSettingsPaneProps) => { - const [preferences, setPreferences] = useState(undefined); + const [preferences, setPreferences] = useState< + AppPreferencesPayload | undefined + >(undefined); useEffect(() => { const fetchData = async () => { const prefs = await GetAppPreferences(); - console.log("prefs", prefs) + console.log("prefs", prefs); setPreferences(prefs.preferences); - } + }; fetchData(); }, []); - // NB: This might be a complex type. const outerDownloadObject = preferences?.preferred_download_directory || {}; - const downloadDirectory = ("custom" in outerDownloadObject) ? outerDownloadObject.custom as string : ""; - const currentDownloadLabel = ("system" in outerDownloadObject) ? "System Download Directory" : downloadDirectory; + const downloadDirectory = + "custom" in outerDownloadObject + ? (outerDownloadObject.custom as string) + : ""; + const currentDownloadLabel = + "system" in outerDownloadObject + ? "System Download Directory" + : downloadDirectory; const reloadPreferences = async () => { const prefs = await GetAppPreferences(); - console.log("prefs", prefs) + console.log("prefs", prefs); setPreferences(prefs.preferences); - } + }; const openDirectoryPicker = async () => { let directory = await open({ @@ -41,49 +53,44 @@ export const MiscSettingsPane = (args: MiscSettingsPaneProps) => { return; // User dismissed the dialog choice } await UpdateAppPreferences({ - preference: PreferenceName.PreferredDownloadDirectory, + preference: PreferenceName.PreferredDownloadDirectory, value: { - custom: directory + custom: directory, } as CustomDirectory, }); await reloadPreferences(); - } + }; const clearDirectory = async () => { await UpdateAppPreferences({ - preference: PreferenceName.PreferredDownloadDirectory, + preference: PreferenceName.PreferredDownloadDirectory, value: { - system: "downloads" + system: "downloads", } as SystemDirectory, }); await reloadPreferences(); - } + }; - return (<> + return (
-
- - This is where downloads are placed after downloading. - The current path is
{currentDownloadLabel}
- - -
-
- ) -} + ); +}; diff --git a/frontend/libs/components/settings-modal/src/lib/settings-modal.tsx b/frontend/libs/components/settings-modal/src/lib/settings-modal.tsx index 9c6e4a364b..72968457ef 100644 --- a/frontend/libs/components/settings-modal/src/lib/settings-modal.tsx +++ b/frontend/libs/components/settings-modal/src/lib/settings-modal.tsx @@ -54,13 +54,9 @@ export const SettingsModal = ({ isOpen, onClose }: SettingsModalProps) => { const renderContent = () => { switch (selectedSection) { case "audio": - return ( - - ); + return ; case "misc": - return ( - - ); + return ; case "accounts": return (
@@ -170,7 +166,9 @@ export const SettingsModal = ({ isOpen, onClose }: SettingsModalProps) => { case "image": return (
- +
); } @@ -208,7 +206,7 @@ export const SettingsModal = ({ isOpen, onClose }: SettingsModalProps) => { ))}
-
+

{sections.find((s) => s.id === selectedSection)?.label} diff --git a/frontend/libs/components/settings-modal/tsconfig.json b/frontend/libs/components/settings-modal/tsconfig.json index a85c4f44ce..f52e6295e5 100644 --- a/frontend/libs/components/settings-modal/tsconfig.json +++ b/frontend/libs/components/settings-modal/tsconfig.json @@ -5,6 +5,9 @@ { "path": "../modal" }, + { + "path": "../label" + }, { "path": "../select" }, diff --git a/frontend/libs/components/settings-modal/tsconfig.lib.json b/frontend/libs/components/settings-modal/tsconfig.lib.json index a0adb87070..c1d7aff072 100644 --- a/frontend/libs/components/settings-modal/tsconfig.lib.json +++ b/frontend/libs/components/settings-modal/tsconfig.lib.json @@ -46,6 +46,9 @@ { "path": "../modal/tsconfig.lib.json" }, + { + "path": "../label/tsconfig.lib.json" + }, { "path": "../select/tsconfig.lib.json" }, diff --git a/frontend/libs/components/switch/.babelrc b/frontend/libs/components/switch/.babelrc new file mode 100644 index 0000000000..1ea870ead4 --- /dev/null +++ b/frontend/libs/components/switch/.babelrc @@ -0,0 +1,12 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [] +} diff --git a/frontend/libs/components/switch/README.md b/frontend/libs/components/switch/README.md new file mode 100644 index 0000000000..8260eb0135 --- /dev/null +++ b/frontend/libs/components/switch/README.md @@ -0,0 +1,7 @@ +# @storyteller/ui-switch + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test @storyteller/ui-switch` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/frontend/libs/components/switch/package.json b/frontend/libs/components/switch/package.json new file mode 100644 index 0000000000..70e60b78ac --- /dev/null +++ b/frontend/libs/components/switch/package.json @@ -0,0 +1,17 @@ +{ + "name": "@storyteller/ui-switch", + "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" + } + } +} diff --git a/frontend/libs/components/switch/src/index.ts b/frontend/libs/components/switch/src/index.ts new file mode 100644 index 0000000000..3f2441cfda --- /dev/null +++ b/frontend/libs/components/switch/src/index.ts @@ -0,0 +1,2 @@ + +export * from './lib/switch'; diff --git a/frontend/libs/components/switch/src/lib/switch.module.css b/frontend/libs/components/switch/src/lib/switch.module.css new file mode 100644 index 0000000000..d0246c74b9 --- /dev/null +++ b/frontend/libs/components/switch/src/lib/switch.module.css @@ -0,0 +1,7 @@ +/* + * Replace this with your own classes + * + * e.g. + * .container { + * } +*/ \ No newline at end of file diff --git a/frontend/libs/components/switch/src/lib/switch.spec.tsx b/frontend/libs/components/switch/src/lib/switch.spec.tsx new file mode 100644 index 0000000000..364763baec --- /dev/null +++ b/frontend/libs/components/switch/src/lib/switch.spec.tsx @@ -0,0 +1,12 @@ +import { render } from '@testing-library/react'; + +import Switch from './switch'; + +describe('Switch', () => { + + it('should render successfully', () => { + const { baseElement } = render(); + expect(baseElement).toBeTruthy(); + }); + +}); diff --git a/frontend/libs/components/switch/src/lib/switch.tsx b/frontend/libs/components/switch/src/lib/switch.tsx new file mode 100644 index 0000000000..5561b4eeda --- /dev/null +++ b/frontend/libs/components/switch/src/lib/switch.tsx @@ -0,0 +1,36 @@ +import { Switch as HeadlessSwitch } from "@headlessui/react"; +import clsx from "clsx"; +import { Fragment } from "react"; + +interface SwitchProps { + enabled: boolean; + setEnabled: (enabled: boolean) => void; + className?: string; +} + +export function Switch({ enabled, setEnabled, className }: SwitchProps) { + return ( + + {({ checked, disabled }) => ( + + )} + + ); +} + +export default Switch; diff --git a/frontend/libs/components/switch/tsconfig.json b/frontend/libs/components/switch/tsconfig.json new file mode 100644 index 0000000000..b3d19d8f5e --- /dev/null +++ b/frontend/libs/components/switch/tsconfig.json @@ -0,0 +1,13 @@ +{ + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../../tsconfig.base.json" +} diff --git a/frontend/libs/components/switch/tsconfig.lib.json b/frontend/libs/components/switch/tsconfig.lib.json new file mode 100644 index 0000000000..f0782e3dd8 --- /dev/null +++ b/frontend/libs/components/switch/tsconfig.lib.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" + ] +} diff --git a/frontend/libs/components/switch/tsconfig.spec.json b/frontend/libs/components/switch/tsconfig.spec.json new file mode 100644 index 0000000000..18b7de51b8 --- /dev/null +++ b/frontend/libs/components/switch/tsconfig.spec.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" + } + ] +} diff --git a/frontend/libs/components/switch/vite.config.ts b/frontend/libs/components/switch/vite.config.ts new file mode 100644 index 0000000000..63d9fe0a36 --- /dev/null +++ b/frontend/libs/components/switch/vite.config.ts @@ -0,0 +1,49 @@ +/// +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/switch', + 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-switch', + 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, + } + }, +})); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b1ebb44995..5eab2998ff 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -2234,6 +2234,10 @@ "@tauri-apps/plugin-dialog": "^2.2.1" } }, + "libs/components/switch": { + "name": "@storyteller/ui-switch", + "version": "0.0.1" + }, "libs/components/tab-selector": { "name": "@storyteller/ui-tab-selector", "version": "0.0.1" @@ -10340,6 +10344,10 @@ "resolved": "libs/components/settings-modal", "link": true }, + "node_modules/@storyteller/ui-switch": { + "resolved": "libs/components/switch", + "link": true + }, "node_modules/@storyteller/ui-tab-selector": { "resolved": "libs/components/tab-selector", "link": true diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 32242d626e..8c9879f034 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -68,6 +68,9 @@ }, { "path": "./libs/components/login-modal" + }, + { + "path": "./libs/components/switch" } ] }