11import type { ValidationMode } from '@jsonforms/core' ;
2- import { reactive , ref , watch } from 'vue' ;
2+ import { reactive , ref , watch , type Ref , type UnwrapRef } from 'vue' ;
3+
4+ export const appstoreLayouts = [ '' , 'demo-and-data' ] as const ;
5+ export type AppstoreLayouts = ( typeof appstoreLayouts ) [ number ] ;
36
47const appstore = reactive ( {
58 exampleName : useHistoryHash ( '' ) ,
69 rtl : false ,
7- formOnly : false ,
10+ layout : useLocalStorage ( 'vuetify-example-layout' , '' ) ,
11+ formOnly : useHistoryHashQuery ( 'form-only' , false as boolean ) ,
12+ activeTab : useHistoryHashQuery ( 'active-tab' , 0 as number ) ,
813 dark : useLocalStorage ( 'vuetify-example-dark' , false ) ,
914 theme : useLocalStorage ( 'vuetify-example-theme' , 'light' ) ,
10- drawer : true ,
15+ drawer : useHistoryHashQuery ( 'drawer' , true as boolean ) ,
1116 settings : false ,
1217 variant : useLocalStorage ( 'vuetify-example-variant' , '' ) ,
1318 iconset : useLocalStorage ( 'vuetify-example-iconset' , 'mdi' ) ,
1419 blueprint : useLocalStorage ( 'vuetify-example-blueprint' , 'md1' ) ,
1520 jsonforms : {
16- readonly : false ,
21+ readonly : useHistoryHashQuery ( 'read-only' , false as boolean ) ,
1722 validationMode : 'ValidateAndShow' as ValidationMode ,
1823 config : {
1924 restrict : true ,
@@ -26,7 +31,6 @@ const appstore = reactive({
2631 hideAvatar : false ,
2732 hideArraySummaryValidation : false ,
2833 enableFilterErrorsBeforeTouch : false ,
29- vuetify : { } ,
3034 } ,
3135 locale : useLocalStorage ( 'vuetify-example-locale' , 'en' ) ,
3236 } ,
@@ -36,12 +40,13 @@ export const useAppStore = () => {
3640 return appstore ;
3741} ;
3842
39- export function useHistoryHash ( initialValue : string ) {
43+ function useHistoryHash ( initialValue : string ) {
4044 const data = ref ( initialValue ) ;
4145
4246 // Function to update data based on URL hash
4347 const updateDataFromHash = ( ) => {
44- const hash = window . location . hash . slice ( 1 ) ;
48+ const hashAndQuery = window . location . hash . slice ( 1 ) ; // Remove the leading '#'
49+ const [ hash , _ ] = hashAndQuery . split ( '?' ) ; // Split hash and query string
4550 if ( hash ) {
4651 try {
4752 data . value = decodeURIComponent ( hash ) ;
@@ -51,17 +56,83 @@ export function useHistoryHash(initialValue: string) {
5156 }
5257 } ;
5358
54- // Update data from URL hash on component mount
59+ // Initial update from URL hash
5560 updateDataFromHash ( ) ;
5661
57- watch (
58- data ,
59- ( newValue ) => {
60- const encodedData = encodeURIComponent ( newValue ) ;
61- window . history . replaceState ( null , '' , `#${ encodedData } ` ) ;
62- } ,
63- { deep : true } ,
64- ) ;
62+ watch ( data , ( newValue ) => {
63+ const encodedData = encodeURIComponent ( newValue ) ;
64+
65+ const currentHash = window . location . hash . slice ( 1 ) ;
66+ const [ , currentQueryString ] = currentHash . split ( '?' ) ; // Extract the query part after ?
67+
68+ window . history . replaceState (
69+ null ,
70+ '' ,
71+ `#${ encodedData } ${ currentQueryString ? '?' + currentQueryString : '' } ` , // Keep the query parameters intact
72+ ) ;
73+ } ) ;
74+
75+ return data ;
76+ }
77+
78+ function useHistoryHashQuery < T extends string | boolean | number > (
79+ queryParam : string ,
80+ initialValue : T ,
81+ ) {
82+ const data : Ref < UnwrapRef < T > > = ref < T > ( initialValue ) ;
83+
84+ // Function to update data based on URL hash
85+ const updateDataFromHash = ( ) => {
86+ const hashAndQuery = window . location . hash . slice ( 1 ) ; // Remove the leading '#'
87+ const [ _ , query ] = hashAndQuery . split ( '?' ) ; // Split hash and query string
88+
89+ const searchParams = new URLSearchParams ( query ) ;
90+ if ( searchParams ) {
91+ try {
92+ const value = searchParams . has ( queryParam )
93+ ? searchParams . get ( queryParam )
94+ : `${ initialValue } ` ;
95+
96+ // Convert the value based on the type of initialValue
97+ if ( typeof initialValue === 'boolean' ) {
98+ // Handle boolean conversion
99+ data . value = ( value === 'true' ) as UnwrapRef < T > ;
100+ } else if ( typeof initialValue === 'number' ) {
101+ data . value = ( value ? parseFloat ( value ) : 0 ) as UnwrapRef < T > ;
102+ } else if ( typeof initialValue === 'string' ) {
103+ // Handle string conversion
104+ data . value = value as UnwrapRef < T > ;
105+ }
106+ } catch ( error ) {
107+ console . error ( 'Error parsing hash:' , error ) ;
108+ }
109+ }
110+ } ;
111+
112+ // Initial update from URL hash
113+ updateDataFromHash ( ) ;
114+
115+ watch ( data , ( newValue ) => {
116+ const encodedData = encodeURIComponent ( newValue ) ;
117+
118+ const hashAndQuery = window . location . hash . slice ( 1 ) ; // Remove the leading '#'
119+ const [ hash , query ] = hashAndQuery . split ( '?' ) ; // Split hash and query string
120+
121+ const searchParams = new URLSearchParams ( query ) ;
122+
123+ if ( newValue === initialValue ) {
124+ // it is the default value so no need to preserve the query paramter
125+ searchParams . delete ( queryParam ) ;
126+ } else {
127+ searchParams . set ( queryParam , encodedData ) ;
128+ }
129+
130+ window . history . replaceState (
131+ null ,
132+ '' ,
133+ `#${ hash } ${ searchParams . size > 0 ? '?' + searchParams : '' } ` , // Keep the query parameters intact
134+ ) ;
135+ } ) ;
65136
66137 return data ;
67138}
0 commit comments