@hybridly/vue 0.4.1 → 0.4.2

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/index.cjs CHANGED
@@ -543,6 +543,12 @@ function useProperties() {
543
543
  function useProperty(path) {
544
544
  return vue.computed(() => dotDiver.getByPath(state.context.value?.view.properties, path));
545
545
  }
546
+ function setProperty(path, value) {
547
+ if (!state.context.value?.view.properties) {
548
+ return;
549
+ }
550
+ dotDiver.setByPath(state.context.value.view.properties, path, vue.toValue(value));
551
+ }
546
552
 
547
553
  function useContext() {
548
554
  return vue.computed(() => state.context.value);
@@ -795,6 +801,16 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
795
801
  const refinements = vue.computed(() => properties[refinementsKeys]);
796
802
  const sortsKey = vue.computed(() => refinements.value.keys.sorts);
797
803
  const filtersKey = vue.computed(() => refinements.value.keys.filters);
804
+ defaultOptions = {
805
+ replace: false,
806
+ ...defaultOptions
807
+ };
808
+ function getSort(name) {
809
+ return refinements.value.sorts.find((sort) => sort.name === name);
810
+ }
811
+ function getFilter(name) {
812
+ return refinements.value.filters.find((sort) => sort.name === name);
813
+ }
798
814
  async function reset(options = {}) {
799
815
  return await core.router.reload({
800
816
  ...defaultOptions,
@@ -825,16 +841,21 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
825
841
  }
826
842
  });
827
843
  }
828
- async function applyFilter(filter, value, options = {}) {
829
- if (!refinements.value.filters.find(({ name }) => name === filter)) {
844
+ async function applyFilter(name, value, options = {}) {
845
+ const filter = getFilter(name);
846
+ if (!filter) {
847
+ console.warn(`[Refinement] Filter "${name} does not exist."`);
830
848
  return;
831
849
  }
850
+ if (["", null].includes(value) || value === filter.default) {
851
+ value = void 0;
852
+ }
832
853
  return await core.router.reload({
833
854
  ...defaultOptions,
834
855
  ...options,
835
856
  data: {
836
857
  [filtersKey.value]: {
837
- [filter]: value === "" ? void 0 : value
858
+ [name]: value
838
859
  }
839
860
  }
840
861
  });
@@ -854,16 +875,22 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
854
875
  function currentFilters() {
855
876
  return refinements.value.filters.filter(({ is_active }) => is_active);
856
877
  }
857
- function isSorting() {
878
+ function isSorting(name) {
879
+ if (name) {
880
+ return currentSorts().some((sort) => sort.name === name);
881
+ }
858
882
  return currentSorts().length !== 0;
859
883
  }
860
- function isFiltering() {
884
+ function isFiltering(name) {
885
+ if (name) {
886
+ return currentFilters().some((filter) => filter.name === name);
887
+ }
861
888
  return currentFilters().length !== 0;
862
889
  }
863
- async function toggleSort(sortName, options) {
864
- const sort = refinements.value.sorts.find(({ name }) => name === sortName);
890
+ async function toggleSort(name, options) {
891
+ const sort = getSort(name);
865
892
  if (!sort) {
866
- console.warn(`[Refinement] Sort "${sortName} does not exist."`);
893
+ console.warn(`[Refinement] Sort "${name} does not exist."`);
867
894
  return;
868
895
  }
869
896
  const next = options?.direction ? sort[options?.direction] : sort.next;
@@ -875,9 +902,22 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
875
902
  }
876
903
  });
877
904
  }
905
+ function bindFilter(name, options = {}) {
906
+ const transform = options?.transformValue ?? ((value) => value);
907
+ const watchFn = options?.watch ?? vue.watch;
908
+ const _ref = vue.ref(transform(refinements.value.filters.find((f) => f.name === name)?.value));
909
+ vue.watch(() => refinements.value.filters.find((f) => f.name === name), (filter) => {
910
+ _ref.value = transform(filter?.value);
911
+ }, { deep: true });
912
+ watchFn(_ref, (value) => applyFilter(name, transform(value), options));
913
+ return _ref;
914
+ }
878
915
  return {
916
+ bindFilter,
879
917
  filters: toReactive(refinements.value.filters),
880
918
  sorts: toReactive(refinements.value.sorts),
919
+ getFilter,
920
+ getSort,
881
921
  reset,
882
922
  toggleSort,
883
923
  isSorting,
@@ -891,6 +931,20 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
891
931
  };
892
932
  }
893
933
 
934
+ function useRoute() {
935
+ const current = vue.ref(hybridly.router.current());
936
+ function matches(name, parameters) {
937
+ return hybridly.router.matches(vue.toValue(name), parameters);
938
+ }
939
+ registerHook("navigated", () => {
940
+ current.value = hybridly.router.current();
941
+ });
942
+ return {
943
+ current: vue.readonly(current),
944
+ matches
945
+ };
946
+ }
947
+
894
948
  exports.can = core.can;
895
949
  exports.route = core.route;
896
950
  exports.router = core.router;
@@ -899,6 +953,7 @@ exports.defineLayout = defineLayout;
899
953
  exports.defineLayoutProperties = defineLayoutProperties;
900
954
  exports.initializeHybridly = initializeHybridly;
901
955
  exports.registerHook = registerHook;
956
+ exports.setProperty = setProperty;
902
957
  exports.useBackForward = useBackForward;
903
958
  exports.useContext = useContext;
904
959
  exports.useDialog = useDialog;
@@ -908,3 +963,4 @@ exports.usePaginator = usePaginator;
908
963
  exports.useProperties = useProperties;
909
964
  exports.useProperty = useProperty;
910
965
  exports.useRefinements = useRefinements;
966
+ exports.useRoute = useRoute;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as vue from 'vue';
2
- import { App, Plugin as Plugin$2, h, PropType, ComputedRef, DeepReadonly } from 'vue';
2
+ import { App, Plugin as Plugin$2, h, PropType, ComputedRef, DeepReadonly, Ref, MaybeRefOrGetter } from 'vue';
3
3
  import * as _hybridly_core from '@hybridly/core';
4
4
  import { RouterContextOptions, Plugin as Plugin$1, RouterContext, Method as Method$1, HybridRequestOptions as HybridRequestOptions$1, UrlResolvable as UrlResolvable$1, registerHook as registerHook$1 } from '@hybridly/core';
5
5
  export { can, route, router } from '@hybridly/core';
@@ -156,6 +156,11 @@ declare const RouterLink: vue.DefineComponent<{
156
156
  declare function useProperties<T extends object, Global extends GlobalHybridlyProperties>(): vue.DeepReadonly<vue.UnwrapNestedRefs<T & Global>>;
157
157
  /** Accesses a property with a dot notation. */
158
158
  declare function useProperty<Override = never, T extends SearchableObject = GlobalHybridlyProperties, P extends Path<T> & string = Path<T> & string, ReturnType = [Override] extends [never] ? PathValue<T, P> : Override>(path: [Override] extends [never] ? P : string): ComputedRef<ReturnType>;
159
+ /**
160
+ * Sets the property at the given path to the given value.
161
+ * Note: this helper is experimental and may change in the future.
162
+ */
163
+ declare function setProperty<Override = never, T extends SearchableObject = GlobalHybridlyProperties, P extends Path<T> & string = Path<T> & string, ValueType = [Override] extends [never] ? PathValue<T, P> : Override>(path: [Override] extends [never] ? P : string, value: ValueType): void;
159
164
 
160
165
  type UrlResolvable = string | URL | Location;
161
166
  type UrlTransformable = BaseUrlTransformable | ((string: URL) => BaseUrlTransformable);
@@ -641,6 +646,11 @@ type AvailableHybridRequestOptions = Omit<HybridRequestOptions$1, 'url' | 'data'
641
646
  interface ToggleSortOptions extends AvailableHybridRequestOptions {
642
647
  direction?: SortDirection;
643
648
  }
649
+ interface BindFilterOptions<T> extends AvailableHybridRequestOptions {
650
+ transformValue?: (value?: T) => any;
651
+ /** If specified, this callback will watch the ref and apply */
652
+ watch?: (ref: Ref<T>, cb: any) => void;
653
+ }
644
654
  declare global {
645
655
  interface FilterRefinement {
646
656
  /**
@@ -671,6 +681,10 @@ declare global {
671
681
  * Whether this filter is hidden.
672
682
  */
673
683
  hidden: boolean;
684
+ /**
685
+ * The default value of the filter.
686
+ */
687
+ default: any;
674
688
  }
675
689
  interface SortRefinement {
676
690
  /**
@@ -745,6 +759,10 @@ declare global {
745
759
  declare function useRefinements<Properties extends object, RefinementsKey extends {
746
760
  [K in keyof Properties]: Properties[K] extends Refinements ? K : never;
747
761
  }[keyof Properties]>(properties: Properties, refinementsKeys: RefinementsKey, defaultOptions?: AvailableHybridRequestOptions): {
762
+ /**
763
+ * Binds a named filter to a ref, applying filters when it changes and updating the ref accordingly.
764
+ */
765
+ bindFilter: <T = any>(name: string, options?: BindFilterOptions<T>) => Ref<T>;
748
766
  /**
749
767
  * Available filters.
750
768
  */
@@ -753,6 +771,14 @@ declare function useRefinements<Properties extends object, RefinementsKey extend
753
771
  * Available sorts.
754
772
  */
755
773
  sorts: SortRefinement[];
774
+ /**
775
+ * Gets a filter by name.
776
+ */
777
+ getFilter: (name: string) => FilterRefinement | undefined;
778
+ /**
779
+ * Gets a sort by name.
780
+ */
781
+ getSort: (name: string) => SortRefinement | undefined;
756
782
  /**
757
783
  * Resets all filters and sorts.
758
784
  */
@@ -760,15 +786,15 @@ declare function useRefinements<Properties extends object, RefinementsKey extend
760
786
  /**
761
787
  * Toggles the specified sort.
762
788
  */
763
- toggleSort: (sortName: string, options?: ToggleSortOptions) => Promise<_hybridly_core.NavigationResponse | undefined>;
789
+ toggleSort: (name: string, options?: ToggleSortOptions) => Promise<_hybridly_core.NavigationResponse | undefined>;
764
790
  /**
765
791
  * Whether a sort is active.
766
792
  */
767
- isSorting: () => boolean;
793
+ isSorting: (name?: string) => boolean;
768
794
  /**
769
795
  * Whether a filter is active.
770
796
  */
771
- isFiltering: () => boolean;
797
+ isFiltering: (name?: string) => boolean;
772
798
  /**
773
799
  * The current sorts.
774
800
  */
@@ -792,7 +818,12 @@ declare function useRefinements<Properties extends object, RefinementsKey extend
792
818
  /**
793
819
  * Applies the given filter.
794
820
  */
795
- applyFilter: (filter: string, value: any, options?: AvailableHybridRequestOptions) => Promise<_hybridly_core.NavigationResponse | undefined>;
821
+ applyFilter: (name: string, value: any, options?: AvailableHybridRequestOptions) => Promise<_hybridly_core.NavigationResponse | undefined>;
822
+ };
823
+
824
+ declare function useRoute(): {
825
+ current: Readonly<vue.Ref<string | undefined>>;
826
+ matches: <T extends string>(name: MaybeRefOrGetter<T>, parameters?: Record<string, any> | undefined) => boolean;
796
827
  };
797
828
 
798
- export { Layout, RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty, useRefinements };
829
+ export { Layout, RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, setProperty, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty, useRefinements, useRoute };
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
- import { shallowRef, ref, unref, triggerRef, defineComponent, toRaw, h, nextTick, createApp, isRef, reactive, readonly, computed, watch, getCurrentInstance, onUnmounted } from 'vue';
1
+ import { shallowRef, ref, unref, triggerRef, defineComponent, toRaw, h, nextTick, createApp, isRef, reactive, readonly, computed, toValue, watch, getCurrentInstance, onUnmounted } from 'vue';
2
2
  import { registerHook as registerHook$1, createRouter, makeUrl, router } from '@hybridly/core';
3
3
  export { can, route, router } from '@hybridly/core';
4
4
  import { debug, random, showPageComponentErrorModal, merge, clone, unsetPropertyAtPath, setValueAtPath } from '@hybridly/utils';
5
5
  import { progress } from '@hybridly/progress-plugin';
6
6
  import { setupDevtoolsPlugin } from '@vue/devtools-api';
7
7
  import qs from 'qs';
8
- import { getByPath } from '@clickbar/dot-diver';
8
+ import { getByPath, setByPath } from '@clickbar/dot-diver';
9
9
  import isEqual from 'lodash.isequal';
10
10
  import { router as router$1 } from 'hybridly';
11
11
 
@@ -535,6 +535,12 @@ function useProperties() {
535
535
  function useProperty(path) {
536
536
  return computed(() => getByPath(state.context.value?.view.properties, path));
537
537
  }
538
+ function setProperty(path, value) {
539
+ if (!state.context.value?.view.properties) {
540
+ return;
541
+ }
542
+ setByPath(state.context.value.view.properties, path, toValue(value));
543
+ }
538
544
 
539
545
  function useContext() {
540
546
  return computed(() => state.context.value);
@@ -787,6 +793,16 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
787
793
  const refinements = computed(() => properties[refinementsKeys]);
788
794
  const sortsKey = computed(() => refinements.value.keys.sorts);
789
795
  const filtersKey = computed(() => refinements.value.keys.filters);
796
+ defaultOptions = {
797
+ replace: false,
798
+ ...defaultOptions
799
+ };
800
+ function getSort(name) {
801
+ return refinements.value.sorts.find((sort) => sort.name === name);
802
+ }
803
+ function getFilter(name) {
804
+ return refinements.value.filters.find((sort) => sort.name === name);
805
+ }
790
806
  async function reset(options = {}) {
791
807
  return await router.reload({
792
808
  ...defaultOptions,
@@ -817,16 +833,21 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
817
833
  }
818
834
  });
819
835
  }
820
- async function applyFilter(filter, value, options = {}) {
821
- if (!refinements.value.filters.find(({ name }) => name === filter)) {
836
+ async function applyFilter(name, value, options = {}) {
837
+ const filter = getFilter(name);
838
+ if (!filter) {
839
+ console.warn(`[Refinement] Filter "${name} does not exist."`);
822
840
  return;
823
841
  }
842
+ if (["", null].includes(value) || value === filter.default) {
843
+ value = void 0;
844
+ }
824
845
  return await router.reload({
825
846
  ...defaultOptions,
826
847
  ...options,
827
848
  data: {
828
849
  [filtersKey.value]: {
829
- [filter]: value === "" ? void 0 : value
850
+ [name]: value
830
851
  }
831
852
  }
832
853
  });
@@ -846,16 +867,22 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
846
867
  function currentFilters() {
847
868
  return refinements.value.filters.filter(({ is_active }) => is_active);
848
869
  }
849
- function isSorting() {
870
+ function isSorting(name) {
871
+ if (name) {
872
+ return currentSorts().some((sort) => sort.name === name);
873
+ }
850
874
  return currentSorts().length !== 0;
851
875
  }
852
- function isFiltering() {
876
+ function isFiltering(name) {
877
+ if (name) {
878
+ return currentFilters().some((filter) => filter.name === name);
879
+ }
853
880
  return currentFilters().length !== 0;
854
881
  }
855
- async function toggleSort(sortName, options) {
856
- const sort = refinements.value.sorts.find(({ name }) => name === sortName);
882
+ async function toggleSort(name, options) {
883
+ const sort = getSort(name);
857
884
  if (!sort) {
858
- console.warn(`[Refinement] Sort "${sortName} does not exist."`);
885
+ console.warn(`[Refinement] Sort "${name} does not exist."`);
859
886
  return;
860
887
  }
861
888
  const next = options?.direction ? sort[options?.direction] : sort.next;
@@ -867,9 +894,22 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
867
894
  }
868
895
  });
869
896
  }
897
+ function bindFilter(name, options = {}) {
898
+ const transform = options?.transformValue ?? ((value) => value);
899
+ const watchFn = options?.watch ?? watch;
900
+ const _ref = ref(transform(refinements.value.filters.find((f) => f.name === name)?.value));
901
+ watch(() => refinements.value.filters.find((f) => f.name === name), (filter) => {
902
+ _ref.value = transform(filter?.value);
903
+ }, { deep: true });
904
+ watchFn(_ref, (value) => applyFilter(name, transform(value), options));
905
+ return _ref;
906
+ }
870
907
  return {
908
+ bindFilter,
871
909
  filters: toReactive(refinements.value.filters),
872
910
  sorts: toReactive(refinements.value.sorts),
911
+ getFilter,
912
+ getSort,
873
913
  reset,
874
914
  toggleSort,
875
915
  isSorting,
@@ -883,4 +923,18 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
883
923
  };
884
924
  }
885
925
 
886
- export { RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty, useRefinements };
926
+ function useRoute() {
927
+ const current = ref(router$1.current());
928
+ function matches(name, parameters) {
929
+ return router$1.matches(toValue(name), parameters);
930
+ }
931
+ registerHook("navigated", () => {
932
+ current.value = router$1.current();
933
+ });
934
+ return {
935
+ current: readonly(current),
936
+ matches
937
+ };
938
+ }
939
+
940
+ export { RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, setProperty, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty, useRefinements, useRoute };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hybridly/vue",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Vue adapter for Hybridly",
5
5
  "keywords": [
6
6
  "hybridly",
@@ -44,9 +44,9 @@
44
44
  "lodash.isequal": "^4.5.0",
45
45
  "nprogress": "^0.2.0",
46
46
  "qs": "^6.11.2",
47
- "@hybridly/core": "0.4.1",
48
- "@hybridly/progress-plugin": "0.4.1",
49
- "@hybridly/utils": "0.4.1"
47
+ "@hybridly/core": "0.4.2",
48
+ "@hybridly/progress-plugin": "0.4.2",
49
+ "@hybridly/utils": "0.4.2"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/lodash": "^4.14.195",