@classic-homes/theme-mcp 0.1.33 → 0.1.35

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.
package/dist/cli.js CHANGED
@@ -2732,6 +2732,576 @@ var component_catalog_default = {
2732
2732
  "AppShell"
2733
2733
  ]
2734
2734
  },
2735
+ {
2736
+ name: "DataPanel",
2737
+ description: "A flexible, draggable panel component supporting pinned, detached, and card modes",
2738
+ category: "layout",
2739
+ importPath: "@classic-homes/theme-svelte",
2740
+ props: [
2741
+ {
2742
+ name: "open",
2743
+ type: "boolean",
2744
+ default: "true",
2745
+ required: false,
2746
+ description: "Panel visibility"
2747
+ },
2748
+ {
2749
+ name: "onOpenChange",
2750
+ type: "(open: boolean) => void",
2751
+ required: false,
2752
+ description: "Callback when visibility changes"
2753
+ },
2754
+ {
2755
+ name: "mode",
2756
+ type: "'pinned' | 'detached'",
2757
+ default: "'pinned'",
2758
+ required: false,
2759
+ description: "Panel mode"
2760
+ },
2761
+ {
2762
+ name: "onModeChange",
2763
+ type: "(mode: PanelMode) => void",
2764
+ required: false,
2765
+ description: "Callback when mode changes"
2766
+ },
2767
+ {
2768
+ name: "variant",
2769
+ type: "'full' | 'card'",
2770
+ default: "'full'",
2771
+ required: false,
2772
+ description: "Panel variant"
2773
+ },
2774
+ {
2775
+ name: "onVariantChange",
2776
+ type: "(variant: PanelVariant) => void",
2777
+ required: false,
2778
+ description: "Callback when variant changes"
2779
+ },
2780
+ {
2781
+ name: "edge",
2782
+ type: "'left' | 'right' | 'top' | 'bottom'",
2783
+ default: "'right'",
2784
+ required: false,
2785
+ description: "Edge to pin to (pinned mode)"
2786
+ },
2787
+ {
2788
+ name: "onEdgeChange",
2789
+ type: "(edge: PanelEdge) => void",
2790
+ required: false,
2791
+ description: "Callback when edge changes"
2792
+ },
2793
+ {
2794
+ name: "expanded",
2795
+ type: "boolean",
2796
+ default: "true",
2797
+ required: false,
2798
+ description: "Whether panel is expanded"
2799
+ },
2800
+ {
2801
+ name: "onExpandedChange",
2802
+ type: "(expanded: boolean) => void",
2803
+ required: false,
2804
+ description: "Callback when expanded state changes"
2805
+ },
2806
+ {
2807
+ name: "title",
2808
+ type: "string",
2809
+ required: false,
2810
+ description: "Panel title"
2811
+ },
2812
+ {
2813
+ name: "subtitle",
2814
+ type: "string",
2815
+ required: false,
2816
+ description: "Panel subtitle"
2817
+ },
2818
+ {
2819
+ name: "actions",
2820
+ type: "DataPanelAction[]",
2821
+ default: "[]",
2822
+ required: false,
2823
+ description: "Footer action buttons"
2824
+ },
2825
+ {
2826
+ name: "constraints",
2827
+ type: "PanelConstraints",
2828
+ default: "defaults",
2829
+ required: false,
2830
+ description: "Size constraints"
2831
+ },
2832
+ {
2833
+ name: "cardConfig",
2834
+ type: "CardConfig",
2835
+ default: "defaults",
2836
+ required: false,
2837
+ description: "Card mode configuration"
2838
+ },
2839
+ {
2840
+ name: "disableClose",
2841
+ type: "boolean",
2842
+ default: "false",
2843
+ required: false,
2844
+ description: "Disable close button"
2845
+ },
2846
+ {
2847
+ name: "disableResize",
2848
+ type: "boolean",
2849
+ default: "false",
2850
+ required: false,
2851
+ description: "Disable resize functionality"
2852
+ },
2853
+ {
2854
+ name: "disableDrag",
2855
+ type: "boolean",
2856
+ default: "false",
2857
+ required: false,
2858
+ description: "Disable drag functionality"
2859
+ },
2860
+ {
2861
+ name: "disableModeSwitch",
2862
+ type: "boolean",
2863
+ default: "false",
2864
+ required: false,
2865
+ description: "Disable mode switching menu"
2866
+ },
2867
+ {
2868
+ name: "persistKey",
2869
+ type: "string",
2870
+ required: false,
2871
+ description: "localStorage key for state persistence"
2872
+ },
2873
+ {
2874
+ name: "snapThreshold",
2875
+ type: "number",
2876
+ default: "20",
2877
+ required: false,
2878
+ description: "Distance for edge snap detection (px)"
2879
+ },
2880
+ {
2881
+ name: "detachThreshold",
2882
+ type: "number",
2883
+ default: "40",
2884
+ required: false,
2885
+ description: "Distance to drag before detaching (px)"
2886
+ },
2887
+ {
2888
+ name: "class",
2889
+ type: "string",
2890
+ required: false,
2891
+ description: "Additional CSS classes"
2892
+ }
2893
+ ],
2894
+ variants: [
2895
+ {
2896
+ name: "mode",
2897
+ values: [
2898
+ "pinned",
2899
+ "detached"
2900
+ ],
2901
+ default: "pinned"
2902
+ },
2903
+ {
2904
+ name: "variant",
2905
+ values: [
2906
+ "full",
2907
+ "card"
2908
+ ],
2909
+ default: "full"
2910
+ },
2911
+ {
2912
+ name: "edge",
2913
+ values: [
2914
+ "left",
2915
+ "right",
2916
+ "top",
2917
+ "bottom"
2918
+ ],
2919
+ default: "right"
2920
+ }
2921
+ ],
2922
+ slots: [
2923
+ {
2924
+ name: "children",
2925
+ description: "Main content",
2926
+ required: false
2927
+ }
2928
+ ],
2929
+ events: [],
2930
+ examples: [
2931
+ {
2932
+ title: "Basic Usage",
2933
+ code: '<script>\n let open = $state(true);\n</script>\n\n<DataPanel bind:open title="Details" subtitle="View information">\n <p>Panel content goes here.</p>\n</DataPanel>'
2934
+ },
2935
+ {
2936
+ title: "Pinned Mode (Default)",
2937
+ description: "The panel attaches to a viewport edge and can be resized along the perpendicular axis.",
2938
+ code: '<DataPanel mode="pinned" edge="right" title="Right Sidebar">\n <p>Pinned to the right edge.</p>\n</DataPanel>'
2939
+ },
2940
+ {
2941
+ title: "Detached Mode",
2942
+ description: "A floating window that can be freely dragged and resized. Snaps to edges when dragged near them.",
2943
+ code: '<DataPanel mode="detached" title="Floating Panel">\n <p>Drag me anywhere!</p>\n</DataPanel>'
2944
+ },
2945
+ {
2946
+ title: "Full Variant (Default)",
2947
+ description: "Traditional sidebar/panel that takes the full width or height of its pinned edge.",
2948
+ code: '<DataPanel variant="full" edge="right">\n <p>Full-height sidebar.</p>\n</DataPanel>'
2949
+ },
2950
+ {
2951
+ title: "Card Variant",
2952
+ description: "Mobile-friendly bottom sheet with snap points. Swipe up to expand, down to collapse.",
2953
+ code: '<DataPanel variant="card" title="Details" subtitle="Swipe to expand">\n <p>Card content with snap points.</p>\n</DataPanel>'
2954
+ },
2955
+ {
2956
+ title: "Pinned Sidebar with Actions",
2957
+ code: `<script>
2958
+ let panelOpen = $state(true);
2959
+
2960
+ const actions = [
2961
+ { label: 'Cancel', variant: 'ghost', onClick: () => (panelOpen = false) },
2962
+ { label: 'Save', variant: 'primary', onClick: handleSave },
2963
+ ];
2964
+ </script>
2965
+
2966
+ <DataPanel
2967
+ bind:open={panelOpen}
2968
+ title="Edit Item"
2969
+ subtitle="Make changes to your item"
2970
+ edge="right"
2971
+ {actions}
2972
+ >
2973
+ <form>
2974
+ <FormField label="Name" name="name" />
2975
+ <FormField label="Description" name="description" type="textarea" />
2976
+ </form>
2977
+ </DataPanel>`
2978
+ },
2979
+ {
2980
+ title: "Detached Floating Panel",
2981
+ code: '<script>\n let inspectorOpen = $state(false);\n</script>\n\n<Button onclick={() => (inspectorOpen = true)}>Open Inspector</Button>\n\n<DataPanel\n bind:open={inspectorOpen}\n mode="detached"\n title="Inspector"\n constraints={{ minWidth: 300, maxWidth: 500 }}\n>\n <div class="space-y-4">\n <p>Inspect element properties here.</p>\n </div>\n</DataPanel>'
2982
+ },
2983
+ {
2984
+ title: "Mobile Bottom Sheet (Card Mode)",
2985
+ code: '<script>\n let detailsOpen = $state(true);\n let expanded = $state(false);\n</script>\n\n<DataPanel\n bind:open={detailsOpen}\n bind:expanded\n variant="card"\n title="Location Details"\n subtitle="123 Main Street"\n cardConfig={{\n maxWidth: 480,\n showDragHandle: true,\n }}\n>\n <div class="space-y-4">\n <img src="/location.jpg" alt="Location" class="w-full rounded" />\n <p>Additional details about this location.</p>\n </div>\n</DataPanel>'
2986
+ },
2987
+ {
2988
+ title: "With State Persistence",
2989
+ code: '<DataPanel title="Preferences" persistKey="user-preferences-panel">\n <p>Panel state (position, size, mode) is saved to localStorage.</p>\n</DataPanel>'
2990
+ },
2991
+ {
2992
+ title: "Custom Header and Footer",
2993
+ code: '<DataPanel title="Custom Panel">\n {#snippet header()}\n <div class="flex items-center gap-2">\n <Avatar size="sm">JD</Avatar>\n <div>\n <p class="font-medium">John Doe</p>\n <p class="text-xs text-muted-foreground">Online</p>\n </div>\n </div>\n {/snippet}\n\n <p>Panel content here.</p>\n\n {#snippet footer()}\n <div class="flex justify-between w-full">\n <Button variant="ghost" size="sm">Help</Button>\n <Button size="sm">Continue</Button>\n </div>\n {/snippet}\n</DataPanel>'
2994
+ },
2995
+ {
2996
+ title: "Controlled Mode",
2997
+ code: `<script>
2998
+ let mode = $state<'pinned' | 'detached'>('pinned');
2999
+ let edge = $state<'left' | 'right' | 'top' | 'bottom'>('right');
3000
+ </script>
3001
+
3002
+ <div class="flex gap-2 mb-4">
3003
+ <Button onclick={() => (mode = 'pinned')}>Pin</Button>
3004
+ <Button onclick={() => (mode = 'detached')}>Detach</Button>
3005
+ <Select bind:value={edge} options={['left', 'right', 'top', 'bottom']} />
3006
+ </div>
3007
+
3008
+ <DataPanel
3009
+ {mode}
3010
+ {edge}
3011
+ onModeChange={(m) => (mode = m)}
3012
+ onEdgeChange={(e) => (edge = e)}
3013
+ title="Controlled Panel"
3014
+ >
3015
+ <p>Mode: {mode}, Edge: {edge}</p>
3016
+ </DataPanel>`
3017
+ }
3018
+ ],
3019
+ relatedComponents: [
3020
+ "Sidebar",
3021
+ "Dialog",
3022
+ "Card",
3023
+ "DashboardLayout"
3024
+ ]
3025
+ },
3026
+ {
3027
+ name: "DataPanelContent",
3028
+ description: "Scrollable content area for DataPanel",
3029
+ category: "layout",
3030
+ importPath: "@classic-homes/theme-svelte",
3031
+ props: [
3032
+ {
3033
+ name: "children",
3034
+ type: "Snippet / ReactNode",
3035
+ required: false,
3036
+ description: "Content to render (required)"
3037
+ },
3038
+ {
3039
+ name: "class",
3040
+ type: "string",
3041
+ required: false,
3042
+ description: "Additional CSS classes"
3043
+ }
3044
+ ],
3045
+ variants: [],
3046
+ slots: [
3047
+ {
3048
+ name: "children",
3049
+ description: "Main content",
3050
+ required: false
3051
+ }
3052
+ ],
3053
+ events: [],
3054
+ examples: [
3055
+ {
3056
+ title: "Basic Usage",
3057
+ code: "<DataPanelContent>\n <p>Your content goes here.</p>\n <p>Overflow content will scroll.</p>\n</DataPanelContent>"
3058
+ }
3059
+ ],
3060
+ relatedComponents: [
3061
+ "DataPanel",
3062
+ "DataPanelHeader",
3063
+ "DataPanelFooter"
3064
+ ]
3065
+ },
3066
+ {
3067
+ name: "DataPanelFooter",
3068
+ description: "Footer component for DataPanel with action buttons",
3069
+ category: "layout",
3070
+ importPath: "@classic-homes/theme-svelte",
3071
+ props: [
3072
+ {
3073
+ name: "actions",
3074
+ type: "DataPanelAction[]",
3075
+ default: "[]",
3076
+ required: false,
3077
+ description: "Array of action button configurations"
3078
+ },
3079
+ {
3080
+ name: "class",
3081
+ type: "string",
3082
+ required: false,
3083
+ description: "Additional CSS classes"
3084
+ }
3085
+ ],
3086
+ variants: [],
3087
+ slots: [
3088
+ {
3089
+ name: "children",
3090
+ description: "Main content",
3091
+ required: false
3092
+ }
3093
+ ],
3094
+ events: [],
3095
+ examples: [
3096
+ {
3097
+ title: "Basic Usage",
3098
+ code: "<script>\n const actions = [\n { label: 'Cancel', variant: 'ghost', onClick: handleCancel },\n { label: 'Save', variant: 'primary', onClick: handleSave },\n ];\n</script>\n\n<DataPanelFooter {actions} />"
3099
+ }
3100
+ ],
3101
+ relatedComponents: [
3102
+ "DataPanel",
3103
+ "DataPanelHeader",
3104
+ "DataPanelContent",
3105
+ "Button"
3106
+ ]
3107
+ },
3108
+ {
3109
+ name: "DataPanelHeader",
3110
+ description: "Header component for DataPanel with title, actions, and mode controls",
3111
+ category: "layout",
3112
+ importPath: "@classic-homes/theme-svelte",
3113
+ props: [
3114
+ {
3115
+ name: "title",
3116
+ type: "string",
3117
+ required: false,
3118
+ description: "Panel title text"
3119
+ },
3120
+ {
3121
+ name: "subtitle",
3122
+ type: "string",
3123
+ required: false,
3124
+ description: "Panel subtitle text"
3125
+ },
3126
+ {
3127
+ name: "mode",
3128
+ type: "'pinned' | 'detached'",
3129
+ required: false,
3130
+ description: "Current panel mode (required)"
3131
+ },
3132
+ {
3133
+ name: "edge",
3134
+ type: "'left' | 'right' | 'top' | 'bottom'",
3135
+ required: false,
3136
+ description: "Current panel edge (required)"
3137
+ },
3138
+ {
3139
+ name: "isExpanded",
3140
+ type: "boolean",
3141
+ required: false,
3142
+ description: "Whether panel is expanded (required)"
3143
+ },
3144
+ {
3145
+ name: "onModeChange",
3146
+ type: "(mode: PanelMode) => void",
3147
+ required: false,
3148
+ description: "Callback when mode changes"
3149
+ },
3150
+ {
3151
+ name: "onEdgeChange",
3152
+ type: "(edge: PanelEdge) => void",
3153
+ required: false,
3154
+ description: "Callback when edge changes"
3155
+ },
3156
+ {
3157
+ name: "onExpandedChange",
3158
+ type: "(expanded: boolean) => void",
3159
+ required: false,
3160
+ description: "Callback when expand state changes"
3161
+ },
3162
+ {
3163
+ name: "onClose",
3164
+ type: "() => void",
3165
+ required: false,
3166
+ description: "Callback when close is clicked"
3167
+ },
3168
+ {
3169
+ name: "disableClose",
3170
+ type: "boolean",
3171
+ default: "false",
3172
+ required: false,
3173
+ description: "Hide close button"
3174
+ },
3175
+ {
3176
+ name: "disableModeSwitch",
3177
+ type: "boolean",
3178
+ default: "false",
3179
+ required: false,
3180
+ description: "Hide mode switching menu"
3181
+ },
3182
+ {
3183
+ name: "showModeMenuOnly",
3184
+ type: "boolean",
3185
+ default: "false",
3186
+ required: false,
3187
+ description: "Only render the mode dropdown"
3188
+ },
3189
+ {
3190
+ name: "class",
3191
+ type: "string",
3192
+ required: false,
3193
+ description: "Additional CSS classes"
3194
+ }
3195
+ ],
3196
+ variants: [
3197
+ {
3198
+ name: "mode",
3199
+ values: [
3200
+ "pinned",
3201
+ "detached"
3202
+ ]
3203
+ },
3204
+ {
3205
+ name: "edge",
3206
+ values: [
3207
+ "left",
3208
+ "right",
3209
+ "top",
3210
+ "bottom"
3211
+ ]
3212
+ }
3213
+ ],
3214
+ slots: [
3215
+ {
3216
+ name: "children",
3217
+ description: "Main content",
3218
+ required: false
3219
+ }
3220
+ ],
3221
+ events: [],
3222
+ examples: [
3223
+ {
3224
+ title: "Basic Usage",
3225
+ code: `<DataPanelHeader
3226
+ title="Details"
3227
+ subtitle="View more information"
3228
+ mode="pinned"
3229
+ edge="right"
3230
+ isExpanded={true}
3231
+ onModeChange={(m) => console.log('Mode:', m)}
3232
+ onEdgeChange={(e) => console.log('Edge:', e)}
3233
+ onClose={() => console.log('Close')}
3234
+ />`
3235
+ }
3236
+ ],
3237
+ relatedComponents: [
3238
+ "DataPanel",
3239
+ "DataPanelContent",
3240
+ "DataPanelFooter"
3241
+ ]
3242
+ },
3243
+ {
3244
+ name: "DataPanelTab",
3245
+ description: "Collapsed tab indicator for pinned DataPanel",
3246
+ category: "layout",
3247
+ importPath: "@classic-homes/theme-svelte",
3248
+ props: [
3249
+ {
3250
+ name: "title",
3251
+ type: "string",
3252
+ default: "'Panel'",
3253
+ required: false,
3254
+ description: "Tab label text"
3255
+ },
3256
+ {
3257
+ name: "edge",
3258
+ type: "'left' | 'right' | 'top' | 'bottom'",
3259
+ required: false,
3260
+ description: "Edge position (required)"
3261
+ },
3262
+ {
3263
+ name: "onclick",
3264
+ type: "() => void",
3265
+ required: false,
3266
+ description: "Click handler to expand panel"
3267
+ },
3268
+ {
3269
+ name: "class",
3270
+ type: "string",
3271
+ required: false,
3272
+ description: "Additional CSS classes"
3273
+ }
3274
+ ],
3275
+ variants: [
3276
+ {
3277
+ name: "edge",
3278
+ values: [
3279
+ "left",
3280
+ "right",
3281
+ "top",
3282
+ "bottom"
3283
+ ]
3284
+ }
3285
+ ],
3286
+ slots: [
3287
+ {
3288
+ name: "children",
3289
+ description: "Main content",
3290
+ required: false
3291
+ }
3292
+ ],
3293
+ events: [],
3294
+ examples: [
3295
+ {
3296
+ title: "Basic Usage",
3297
+ code: `<DataPanelTab title="Details" edge="right" onclick={() => console.log('Expand panel')} />`
3298
+ }
3299
+ ],
3300
+ relatedComponents: [
3301
+ "DataPanel",
3302
+ "DataPanelHeader"
3303
+ ]
3304
+ },
2735
3305
  {
2736
3306
  name: "DataTable",
2737
3307
  description: "Powerful data table with native Svelte 5 runes - sorting, filtering, pagination, virtualization, and inline editing",
@@ -13439,6 +14009,215 @@ var pattern_library_default = {
13439
14009
  </DropdownMenu.Content>
13440
14010
  </DropdownMenu.Root>`
13441
14011
  }
14012
+ ],
14013
+ panels: [
14014
+ {
14015
+ id: "panel-pinned-sidebar",
14016
+ name: "Pinned Sidebar Panel",
14017
+ description: "Pinned sidebar panel for app navigation, data display, or tool palettes. Attaches to viewport edge with resize and collapse capabilities.",
14018
+ useCase: "Property details, settings panels, inspector tools",
14019
+ components: [
14020
+ "DataPanel",
14021
+ "DataPanelContent"
14022
+ ],
14023
+ props: {
14024
+ mode: "'pinned'",
14025
+ edge: "'left' | 'right' | 'top' | 'bottom'",
14026
+ title: "string",
14027
+ subtitle: "string",
14028
+ expanded: "boolean",
14029
+ persistKey: "string"
14030
+ },
14031
+ example: `<script lang="ts">
14032
+ import { DataPanel } from '@classic-homes/theme-svelte';
14033
+
14034
+ let open = $state(true);
14035
+ let expanded = $state(true);
14036
+ </script>
14037
+
14038
+ <DataPanel
14039
+ bind:open
14040
+ bind:expanded
14041
+ mode="pinned"
14042
+ edge="right"
14043
+ title="Property Details"
14044
+ subtitle="View and edit property information"
14045
+ persistKey="property-details-panel"
14046
+ >
14047
+ <div class="space-y-4">
14048
+ <div>
14049
+ <label class="text-sm font-medium">Address</label>
14050
+ <p class="text-muted-foreground">123 Main Street</p>
14051
+ </div>
14052
+ <div>
14053
+ <label class="text-sm font-medium">Price</label>
14054
+ <p class="text-muted-foreground">$450,000</p>
14055
+ </div>
14056
+ </div>
14057
+ </DataPanel>`
14058
+ },
14059
+ {
14060
+ id: "panel-detached-floating",
14061
+ name: "Detached Floating Panel",
14062
+ description: "Floating draggable panel for tools, inspectors, or secondary content. Can be freely positioned and snaps to edges when dragged nearby.",
14063
+ useCase: "Tool palettes, inspectors, debug panels, floating editors",
14064
+ components: [
14065
+ "DataPanel",
14066
+ "DataPanelContent"
14067
+ ],
14068
+ props: {
14069
+ mode: "'detached'",
14070
+ title: "string",
14071
+ constraints: "PanelConstraints",
14072
+ snapThreshold: "number"
14073
+ },
14074
+ example: `<script lang="ts">
14075
+ import { DataPanel, Button } from '@classic-homes/theme-svelte';
14076
+
14077
+ let inspectorOpen = $state(false);
14078
+ </script>
14079
+
14080
+ <Button onclick={() => inspectorOpen = true}>Open Inspector</Button>
14081
+
14082
+ <DataPanel
14083
+ bind:open={inspectorOpen}
14084
+ mode="detached"
14085
+ title="Element Inspector"
14086
+ subtitle="Inspect selected element"
14087
+ constraints={{ minWidth: 320, maxWidth: 480, minHeight: 300 }}
14088
+ snapThreshold={30}
14089
+ >
14090
+ <div class="space-y-4">
14091
+ <div class="p-3 bg-muted rounded">
14092
+ <code class="text-sm">&lt;div class="container"&gt;</code>
14093
+ </div>
14094
+ <div>
14095
+ <h4 class="font-medium mb-2">Properties</h4>
14096
+ <ul class="text-sm space-y-1">
14097
+ <li>Width: 100%</li>
14098
+ <li>Padding: 16px</li>
14099
+ </ul>
14100
+ </div>
14101
+ </div>
14102
+ </DataPanel>`
14103
+ },
14104
+ {
14105
+ id: "panel-card-mobile",
14106
+ name: "Mobile Bottom Sheet Card",
14107
+ description: "Mobile-optimized bottom sheet card with swipe gestures and snap points. Expands from bottom edge with configurable height stops.",
14108
+ useCase: "Mobile detail views, contextual information, quick actions",
14109
+ components: [
14110
+ "DataPanel",
14111
+ "DataPanelContent",
14112
+ "Button"
14113
+ ],
14114
+ props: {
14115
+ variant: "'card'",
14116
+ cardConfig: "CardConfig",
14117
+ expanded: "boolean"
14118
+ },
14119
+ example: `<script lang="ts">
14120
+ import { DataPanel, Button } from '@classic-homes/theme-svelte';
14121
+
14122
+ let open = $state(true);
14123
+ let expanded = $state(false);
14124
+ </script>
14125
+
14126
+ <DataPanel
14127
+ bind:open
14128
+ bind:expanded
14129
+ variant="card"
14130
+ title="Location Details"
14131
+ subtitle="123 Main Street, Anytown"
14132
+ cardConfig={{
14133
+ maxWidth: 480,
14134
+ showDragHandle: true,
14135
+ borderRadius: 20,
14136
+ }}
14137
+ >
14138
+ <div class="space-y-4">
14139
+ <img src="/location-photo.jpg" alt="Location" class="w-full h-40 object-cover rounded-lg" />
14140
+ <p class="text-muted-foreground">
14141
+ A beautiful property located in the heart of downtown.
14142
+ </p>
14143
+ <div class="flex gap-2">
14144
+ <Button class="flex-1">Get Directions</Button>
14145
+ <Button variant="outline" class="flex-1">Save</Button>
14146
+ </div>
14147
+ </div>
14148
+ </DataPanel>`
14149
+ },
14150
+ {
14151
+ id: "panel-with-actions",
14152
+ name: "Panel with Footer Actions",
14153
+ description: "Data panel with action buttons in the footer for confirming changes, saving data, or navigation between steps.",
14154
+ useCase: "Edit forms, confirmation dialogs, wizard steps",
14155
+ components: [
14156
+ "DataPanel",
14157
+ "DataPanelContent",
14158
+ "FormField",
14159
+ "Button"
14160
+ ],
14161
+ props: {
14162
+ actions: "DataPanelAction[]",
14163
+ title: "string"
14164
+ },
14165
+ example: `<script lang="ts">
14166
+ import { DataPanel, FormField } from '@classic-homes/theme-svelte';
14167
+ import type { DataPanelAction } from '@classic-homes/data-panel-core';
14168
+
14169
+ let open = $state(true);
14170
+ let saving = $state(false);
14171
+ let formData = $state({ name: '', email: '' });
14172
+
14173
+ async function handleSave() {
14174
+ saving = true;
14175
+ await fetch('/api/user', {
14176
+ method: 'PATCH',
14177
+ body: JSON.stringify(formData),
14178
+ });
14179
+ saving = false;
14180
+ open = false;
14181
+ }
14182
+
14183
+ const actions: DataPanelAction[] = $derived([
14184
+ {
14185
+ label: 'Cancel',
14186
+ variant: 'ghost',
14187
+ onClick: () => open = false,
14188
+ disabled: saving,
14189
+ },
14190
+ {
14191
+ label: 'Save Changes',
14192
+ variant: 'primary',
14193
+ onClick: handleSave,
14194
+ loading: saving,
14195
+ },
14196
+ ]);
14197
+ </script>
14198
+
14199
+ <DataPanel
14200
+ bind:open
14201
+ title="Edit Profile"
14202
+ subtitle="Update your account information"
14203
+ edge="right"
14204
+ {actions}
14205
+ >
14206
+ <form class="space-y-4">
14207
+ <FormField
14208
+ label="Name"
14209
+ name="name"
14210
+ bind:value={formData.name}
14211
+ />
14212
+ <FormField
14213
+ label="Email"
14214
+ type="email"
14215
+ name="email"
14216
+ bind:value={formData.email}
14217
+ />
14218
+ </form>
14219
+ </DataPanel>`
14220
+ }
13442
14221
  ]
13443
14222
  };
13444
14223